1. 程式人生 > >iOS 視頻字幕srt文件解析

iOS 視頻字幕srt文件解析

數組 pragma svi 一段 文字 some nsbundle play 示例

問題描述:視頻播放時需要配套字幕

思路是先解析好字幕(中英文)再同步字幕(在播放器時間更新方法中添加對應時間下的字幕)

一、關於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:@"\n"];
            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:@"\n%@",[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解析說明)

iOS 視頻字幕srt文件解析