美文网首页iOS开发iOS技术交流收藏
iOS播放器添加字幕(vtt篇)

iOS播放器添加字幕(vtt篇)

作者: chasitu | 来源:发表于2018-09-21 10:23 被阅读787次

    因为我们公司APP有国外的用户,所以我们APP播放器的字幕需要我们苦逼的程序员实现多语言字幕,客户可以随时切换,看需求完全合理,

    问题:给已有的播放器添加字幕,支持多语言,客户随时可以切换
    解决:

    注:关于UI搭建相关的操作我这里就不多讲解,只说VTT解析的部分,

    第一步:发送请求给服务器获取vtt文件地址
    文件地址(大部分都是vtt结尾)
    第二步:使用该地址去读取文件
    NSString *text = [NSString stringWithContentsOfURL:[NSURL URLWithString:url] encoding:NSUTF8StringEncoding error:nil];
    

    注:如果使用该方法读取文件获取的text=null的话,是后端提供的文件格式有误,让后端修改,如果后端不懂怎么改格式的话那就跟我一样下一步操作,vtt格式本质上就是txt文本,

    第三步:mac上用终端创建txt文本(如正常读取文件,请略过这一步)

    注:用终端创建的txt文件,本地先测试一下,正常发给后端按照这个格式上传(后端其实就是修改后缀直接上传就行)
    ( 1 )打开终端,cd 到想要创建 txt 文本文件的目录(如桌面)

    cd /Users/userName/Desktop
    

    ( 2 )使用 vi 创建 txt 文本文件

    sudo vi fileName.txt 
    

    ( 3 )保存退出

    :wq  
    
    第四步:获得数据解析
    vtt文本格式

    ( 1 )首先去掉前面和后面多余的字符串留下如下的格式数组
    编号
    时间
    内容
    空格

    NSString *text = [NSString stringWithContentsOfURL:[NSURL URLWithString:url] encoding:NSUTF8StringEncoding error:nil];
        if ([text containsString:@"WEBVTT"]) {
            text = [text stringByReplacingOccurrencesOfString:@"WEBVTT" withString:@""];
        }
        NSMutableArray *textMutiArr = [NSMutableArray arrayWithArray:[text componentsSeparatedByString:@"\r\n"]];
        if (textMutiArr.count >= 2 && [textMutiArr[0] isEqualToString:@""] && [textMutiArr[0] isEqualToString:textMutiArr[1]]) {
            [textMutiArr removeObjectsInRange:NSMakeRange(0, 2)];
        }
        if (textMutiArr.count>=1 && [textMutiArr.lastObject isEqualToString:@""] && [textMutiArr.lastObject isEqualToString:textMutiArr[textMutiArr.count-2]]) {
            [textMutiArr removeLastObject];
        }
    

    ( 2 )获取字幕数组之后开始解析

    NSMutableArray *textMutiArr = [self mutableArrayWithURL:url];//获取正常格式数组
        NSMutableArray *data = [NSMutableArray array];
        NSInteger number = textMutiArr.count;
        SHCourseDetailSubtitlesModel *model;
        for (NSInteger i = 0; i < number; i++) {
            if ((i%4) == 0) {
                model = [[SHCourseDetailSubtitlesModel alloc] init];
                [data addObject:model];
                model.index = textMutiArr[i];
            }else if ((i%4) == 1){
                NSString *time = textMutiArr[i];
                NSArray *timeArr = [time componentsSeparatedByString:@"-->"];
                model.starTime = [self timeIntervalWithString:timeArr[0]];
                model.endTime = [self timeIntervalWithString:timeArr[1]];
            }else if ((i%4) == 2){
                model.content = textMutiArr[i];
            }else{
                model = nil;
            }
        }
        self.subtitlesView.dataSource = data;//赋值
    

    注:因为分割数组里面每四组数据是一套模型,所以数据模型放在for循环外,第一次进来分配空间加入数组,然后四个值都赋值之后置空销毁重新分配空间加入数组,如果小伙伴们不理解的话可以在评论区留言给我

    ( 3 )附上时间解析方法,比较简单,不想自己写代码的小伙伴可以直接复制

    - (CGFloat)timeIntervalWithString:(NSString *)string
    {
        NSArray *timeArr = [string componentsSeparatedByString:@":"];
        CGFloat hours = [timeArr[0] floatValue]*60.0*60.0;
        CGFloat minute = [timeArr[1] floatValue]*60.0;
        CGFloat seconds = [timeArr[2] floatValue];
        return hours+minute+seconds;
    }
    
    第五步:设置定时器更新数据就可以了

    ( 1 )设置定时器(为了保证字幕显示精度,设置了300毫秒)

    self.timer = [NSTimer timerWithTimeInterval:0.3 target:self selector:@selector(refreshSubtitles) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    
    

    注:设置定时器一定要记得退出页面操作时销毁定时器,销毁方法千万不要写在dealloc方法里面,因为当前页面有定时器的话dealloc方法不会调用,

    [self.timer invalidate];
    self.timer = nil;
    

    ( 2 )定时器回调更新数据(这里使用谓词查询)

    - (void)refreshSubtitles//定时器回调
    {
        CMTime time = self.myPlayer.currentTime;//获取当前时间
        CGFloat curentTime = CMTimeGetSeconds(time);//转成秒
        NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"starTime<=%f AND endTime>=%f",curentTime,curentTime]];
        NSArray *arr =  [self.subtitlesView.dataSource filteredArrayUsingPredicate:predicate];
        if (arr.count>0) {//如当前时间段有字幕就显示
            SHCourseDetailSubtitlesModel *mode = arr[0];//获取的字幕是否是当前显示的字幕,如是就返回无操作
            if (self.subtitlesView.selectIndex == mode.index.integerValue-1) return;
            self.subtitlesView.selectIndex = mode.index.integerValue-1;
        }else{//反之就隐藏字幕视图
            self.subtitlesView.hidden = YES;
        }
    }
    

    代码里面都做了注释,如果不懂或者有误的可以留言给我,我们一起讨论,用for循环查询方法小伙伴们肯定都会,我就不在这里写给大家啦!

    相关文章

      网友评论

        本文标题:iOS播放器添加字幕(vtt篇)

        本文链接:https://www.haomeiwen.com/subject/wownnftx.html