zoukankan      html  css  js  c++  java
  • iOS 视频字幕srt文件解析

    问题描述:视频播放时需要配套字幕

    思路是先解析好字幕(中英文)再同步字幕(在播放器时间更新方法中添加对应时间下的字幕)

    一、关于srt文件

    1.1打开方式

     在srt文件右键选择“其他”->应用程序->文本编辑器.app,使用文本编辑器查看

    1.2格式说明

    1
    00:00:03,960 --> 00:00:09,260
    《60秒经济学探奇》 第六节:理性选择理论
    60 Second Adventures in Economics -- Number six: Rational Choice Theory
    
    2
    00:00:09,290 --> 00:00:13,950
    运行一个经济体 最让人头疼的因素莫过于人
    Of all the things to factor in when running an economy, the most troublesome is people.
    
    3
    00:00:13,950 --> 00:00:16,460
    总体而言 人是理性的
    Now by and large -- humans are a rational lot.
    
    4
    00:00:16,460 --> 00:00:20,230
    价格上涨时 人们会供给更多 购买更少
    When the price of something rises people will supply more of it -- and buy less of it.
    
    5
    00:00:20,230 --> 00:00:24,180
    如果通胀上升 人们会要求更高工资
    If they expect inflation to go up -- people will usually ask for higher wages --
    
    6
    00:00:24,180 --> 00:00:25,660
    只是可能得不到
    (though they might not get them)
    
    7
    00:00:25,660 --> 00:00:28,660
    看到一个国家的利率或汇率下降时
    And if they can see interest or exchange rates falling in one country,

    一般情况下的srt文件格式非常固定,上面的格式可以看成
    数字
    起始时间 --> 结束时间
    字幕内容(可以多行)
    空行

    这种固定样式,每五行一个完整字幕行;

    1.3解析方法

    #pragma mark -字幕
    -(void)getVideoSubtitles
    {
    //    NSString *pathStr = [[NSBundle mainBundle] pathForResource:@"VideoSubtitles1" ofType:@"srt"];
    //    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:pathStr]];
        NSString *pathStr = [self.subTitlePath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:pathStr]];
        
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (!error) {
                NSString *string=[[NSMutableString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                //按行分割存放到数组中
                NSArray *singlearray = [string componentsSeparatedByString:@"
    "];
                NSMutableArray *begintimearray1 = [NSMutableArray array];
                NSMutableArray *endtimearray1 = [NSMutableArray array];
                NSMutableArray * subtitlesarray1 = [NSMutableArray array];
                NSString *subStr = @"";
                for (int i = 0; i < singlearray.count; i++) {
                    if ((i % 5) == 0) {
                        
                    }else if ((i % 5) == 1) {
                        //时间
                        NSString *timeStr = [singlearray objectAtIndex:i];
                        NSRange range2 = [timeStr rangeOfString:@" --> "];
                        if (range2.location != NSNotFound) {
                            NSString *beginstr = [timeStr substringToIndex:range2.location];
                            NSString *endstr = [timeStr substringFromIndex:range2.location+range2.length];
                            
                            
                            NSArray * arr = [beginstr componentsSeparatedByString:@":"];
                            NSArray * arr1 = [arr[2] componentsSeparatedByString:@","];
                            
                            //将开始时间数组中的时间换化成秒为单位的
                            float teim=[arr[0] floatValue] * 60*60 + [arr[1] floatValue]*60 + [arr1[0] floatValue] + [arr1[1] floatValue]/1000;
                            //将float类型转化成NSNumber类型才能存入数组
                            NSNumber *beginnum = [NSNumber numberWithFloat:teim];
                            [begintimearray1 addObject:beginnum];
                            
                            NSArray * array = [endstr componentsSeparatedByString:@":"];
                            NSArray * arr2 = [array[2] componentsSeparatedByString:@","];
                            //将结束时间数组中的时间换化成秒为单位的
                            float fl=[array[0] floatValue] * 60*60 + [array[1] floatValue]*60 + [arr2[0] floatValue] + [arr2[1] floatValue]/1000;
                            NSNumber *endnum = [NSNumber numberWithFloat:fl];
                            [endtimearray1 addObject:endnum];
                        }
                    }else
                    {
                        if ((i % 5) == 2)
                        {
                            //中文字幕
                            subStr = [NSString stringWithFormat:@"%@",[singlearray objectAtIndex:i]];
                        }else if ((i % 5) == 3)
                        {
                            //英文原文
                            subStr = [subStr stringByAppendingFormat:@"
    %@",[singlearray objectAtIndex:i]];
                            [subtitlesarray1 addObject:subStr];
                            subStr = @"";
                        }
                        
                    }
                }
                dispatch_async(dispatch_get_main_queue(), ^{
                    _beginTimeSubArr = begintimearray1;
                    _endTimeSubArr = endtimearray1;
                    _subtitleArr = subtitlesarray1;
                });
                NSLog(@" 开始时间数组-=-=-==-=%@",begintimearray1);
                NSLog(@" 结束时间数组-=-=-==-=%@",endtimearray1);
                NSLog(@" 字幕数组-=-=-==-=%@",subtitlesarray1);
                
            }else{
                NSLog(@"error  is  %@",error.localizedDescription);
            }
        }];
        [dataTask resume];
        
    }

    这里需要拿到的是一段字幕的开始时间、结束时间以及字幕文字三个内容,分别存入三个数组中,时间的单位换算成秒。

    1.4同步方法

    #pragma mark-更新方法
    
    -(void)update{
    //    NSLog(@"---定时器方法---");
        _labCurrentTime.text =[self TimeformatFromSeconds:self.player.currentPlaybackTime];
        
        CGFloat current = self.player.currentPlaybackTime;
        CGFloat total = self.player.duration;
        CGFloat able = self.player.playableDuration;
        [_slider setValue:current/total animated:YES];
        [_progressView setProgress:able/total animated:YES];
    //    NSLog(@"打印总时长:%.2f",self.player.duration);
        
        self.videoStudyPecent = (current/total)*100;
    //    NSLog(@"video--_beginTimeSubArr:%ld",_beginTimeSubArr.count);
        //字幕同步
        NSInteger currentSecond = self.player.currentPlaybackTime;
        for (int i = 0; i<_beginTimeSubArr.count ; i++) {
            
            NSInteger beginarr =  [_beginTimeSubArr[i] integerValue];
            NSInteger endarr = [_endTimeSubArr[i]integerValue];
            if (currentSecond > beginarr && currentSecond< endarr) {
                //同步字幕
                _subtitleLab.text = _subtitleArr[i];
    //            NSLog(@" 字幕  %@",_subtitleArr[i]);
            }
        }
        
        
    //    NSLog(@"打印视频学习比例%ld",self.videoStudyPecent);
    }

    在播放器的时间更新方法中,遍历字幕起始时间数组,根据当前时间是否处于一段字幕的开始以及结束时间的时间段内来更新字幕文字。如果字幕文字显示与声音有出入,可以试着调整解析时的字幕对应时间精度。

    二、补充

    2.1 srt文件

    上传了一份示例视频以及配套的srt文件到csdn上,有需要的可以下载,用来测试声文同步

    下载地址:http://download.csdn.net/download/wusangtongxue/10106389

    2.2 参考网址:

    http://www.cnblogs.com/ruixin2222/p/5040831.html(主要参考博客)
    http://blog.csdn.net/hhbgk/article/details/22435723(安卓端的字幕srt解析说明)
  • 相关阅读:
    springMVC将处理的后的数据通过post方法传给页面时,可能会出现乱码问题,下面提出解决post乱码问题的方法
    div3的e题有点水呀
    鸽天的放鸽序列---牛客网
    CodeForces
    NOIP2009 压轴---最优贸易
    在加权无向图上求出一条从1号结点到N号结点的路径,使路径上第K+1大的边权尽量小
    好久没写题解了
    皇宫看守问题(带权树上独立集)
    树的最大独立集合问题
    拓扑排序+动态规划
  • 原文地址:https://www.cnblogs.com/wusang/p/7794207.html
Copyright © 2011-2022 走看看