记录一个iOS实现视频分片缓存拖拽快进不能播放的问题

代码现状

首先来看一下我们将视频数据塞给请求的代码

复制代码
- (void)finishLoadingWithLoadingRequest:(IdiotResourceTask *)task {
   // printf("哈哈执行到这里执行到到这里\n");
    printf("哈哈哈数量数量%ld\n", self.taskList.count);

    //填充信息
    task.loadingRequest.contentInformationRequest.contentType = @"video/mp4";
    task.loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;
    task.loadingRequest.contentInformationRequest.contentLength = task.resource.fileLength;
    
    if (task.resource.fileLength <= 0) {
        NSLog(@"requestTask.fileLength <= 0");
    }
    printf("哈哈哈1111执行执行执行%lld点 %lld 一 %lld %p  %p\n", task.loadingRequest.dataRequest.requestedOffset,task.loadingRequest.dataRequest.currentOffset, task.resource.requestOffset, task.loadingRequest, task);

    //读文件,填充数据
    long long cacheLength = task.resource.cacheLength;
    long long requestedOffset = task.loadingRequest.dataRequest.requestedOffset;
    if (task.loadingRequest.dataRequest.currentOffset != 0) {
        requestedOffset = task.loadingRequest.dataRequest.currentOffset;
    }
    
    if (requestedOffset < task.resource.requestOffset) {
    /*这里是说明视频请求对象的offset小于当前任务的resouce 的offset
    注意:task.resouce,是一开始播放创建的resouce或者拖拽之后创建的resouce
    即一段连续不中断的资源对应一个resouce,
    如果当前当前视频请求的offset小于task.resouce.offset,说明
    该resouce 和当前request没有重合部分,要返回
    注意这里不能加上 请求的.dataRequest.requestedLength 然后和task.resouce.requestoffset比较,因为填充数据要从请求的开头就是offset开始填充
    */
        printf("哈哈哈返回111111 \n");
        return;
    }
    
    long long paddingOffset = requestedOffset - task.resource.requestOffset;
    
    long long canReadLength = cacheLength - paddingOffset;
    
    if (canReadLength <= 0) {
        printf("哈哈哈返回222222 %lld\n", canReadLength);
        return;
    }
    
    long long respondLength = MIN(canReadLength, task.loadingRequest.dataRequest.requestedLength);
    
    NSFileHandle * handle = [IdiotFileManager fileHandleForReadingAtPath:task.resource.cachePath];
    
    [handle seekToFileOffset:paddingOffset];
    
    [task.loadingRequest.dataRequest respondWithData:[handle readDataOfLength:[[NSNumber numberWithLongLong:respondLength] unsignedIntegerValue]]];
//    printf("哈哈哈匹配到匹配到的长度%lld %lld %lld  %lld  %lld\n",respondLength,task.loadingRequest.dataRequest.requestedLength, task.loadingRequest.dataRequest.requestedOffset, task.loadingRequest.dataRequest.currentOffset, task.resource.requestOffset);
    [handle closeFile];
    
    //如果完全响应了所需要的数据,则完成
    long long nowendOffset = requestedOffset + canReadLength;
    long long reqEndOffset = task.loadingRequest.dataRequest.requestedOffset + task.loadingRequest.dataRequest.requestedLength;
    printf("哈哈哈哈差别差别%lld\n",reqEndOffset - nowendOffset);
    if (nowendOffset >= reqEndOffset) {
        [task.loadingRequest finishLoading];
        printf("哈哈哈主动删除%lld %lld %p\n",nowendOffset, reqEndOffset, task);
        [self removeLoadingRequest:task.loadingRequest];
        
        return;
    }
    
}

遇到的问题

拖拽之后的操作

复制代码
- (void)seekToTime:(NSTimeInterval)time completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
    if (self.totalTime > 0) {
        CMTime seekTime = CMTimeMake(time, 1);
        WEAKSELF
        [_player seekToTime:seekTime toleranceBefore:kCMTimeZero toleranceAfter:CMTimeMake(1, 1) completionHandler:^(BOOL finished) {
            // 视频跳转回调
                [weakSelf play];
    } else {
        self.seekTime = time;
    }
}

操作之后的结果发现视频不能播放了

查看执行的流程如下

后来经过多次调试发现,是我们seek的时候没有暂停,造成原来的请求还在,就会获取一个offset很小的请求,从而移除拖动之后的请求,造成无法播放

解决方法

修改之后的代码

就是seek之前 pause

复制代码
- (void)seekToTime:(NSTimeInterval)time completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
    self.resourceLoader.seek = YES;
    if (self.totalTime > 0) {
        [self.player pause];

        CMTime seekTime = CMTimeMake(time, 1);
        WEAKSELF
        [_player seekToTime:seekTime toleranceBefore:CMTimeMake(1,1) toleranceAfter:CMTimeMake(1,1) completionHandler:^(BOOL finished) {
            [weakSelf play];
        }];
    } else {
        self.seekTime = time;
    }
}

表现

拖拽之后,视频可以正常播放

相关推荐
EasyCVR7 小时前
国标GB28181视频监控平台EasyCVR夏季安防高风险场景的解决方案
人工智能·音视频
Cutecat_7 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
学术头条9 小时前
清华团队开源SCAIL-2:角色动画告别骨骼依赖,端到端还原视频中动作细节
人工智能·科技·机器学习·ai·开源·音视频·agi
做萤石二次开发的哈哈10 小时前
AI 陪护机器人硬件如何接入萤石ERTC 实现实时通话?
人工智能·音视频·实时音视频·萤石开放平台
禹亮科技10 小时前
上海临港100㎡大型跨国会议室音视频集成方案(思科Webex+思必驰AI音频)
人工智能·音视频·思必驰吸顶麦·禹亮科技
爱吃骨头的鱼儿11 小时前
h264码流结构
音视频·h.264
大蚂蚁2号12 小时前
深度解析:2026短视频批量生成底层技术、架构演进与企业落地实战
架构·音视频
AOwhisky12 小时前
Redis 学习笔记(第四期):高可用与集群(哨兵 + Cluster + 容器化)
linux·运维·数据库·redis·笔记·学习·缓存
大熊猫侯佩12 小时前
WWDC26 SwiftUI 进化之路:砸碎黑盒,彻底迎来开发自由!
ios·swiftui·swift