iOS开发iOS技术交流收藏

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

2018-09-21  本文已影响787人  chasitu

因为我们公司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循环查询方法小伙伴们肯定都会,我就不在这里写给大家啦!

上一篇下一篇

猜你喜欢

热点阅读