如何使用Objective-C实现WEBVTT字幕格式转SRT格式?
使用Objective-C实现WEBVTT到SRT字幕格式转换
我来给你详细讲讲怎么用Objective-C实现WEBVTT到SRT的转换吧~首先得先搞清楚两种格式的核心差异,这样转换起来才不会踩坑:
格式差异对比
WEBVTT格式特点:
- 开头有固定的
WEBVTT标识行- 时间格式为
HH:MM:SS.mmm(小时部分可省略,比如示例中的00:08.000实际是00:00:08.000)- 字幕块由序号(可选)、时间线、多行内容组成
SRT格式特点:
- 无开头标识
- 时间格式为
HH:MM:SS,mmm(必须补全小时,用逗号分隔毫秒)- 每个字幕块严格遵循「序号 → 时间线 → 内容 → 空行」的结构
转换步骤
- 第一步:清理WEBVTT原始内容,去掉开头的
WEBVTT行,同时过滤掉多余的空行和注释(如果存在) - 第二步:按空行分割内容,得到单个字幕块
- 第三步:逐个处理每个字幕块:
- 提取或生成字幕序号(WEBVTT有纯数字序号就沿用,没有则自动生成递增序号)
- 转换时间线:把时间中的
.替换为,, 并补全缺失的小时部分 - 保留原字幕内容(支持多行)
- 第四步:按照SRT格式拼接所有处理后的字幕块,块之间用空行分隔
Objective-C实现代码
下面是一个完整的工具类实现,包含所有转换逻辑:
#import <Foundation/Foundation.h> @interface SubtitleConverter : NSObject /// 将WEBVTT格式内容转换为SRT格式 /// @param webvttContent 原始WEBVTT字符串内容 + (NSString *)convertWEBVTTToSRT:(NSString *)webvttContent; @end @implementation SubtitleConverter + (NSString *)convertWEBVTTToSRT:(NSString *)webvttContent { if (!webvttContent || webvttContent.length == 0) { return @""; } // 1. 清理内容:移除开头的WEBVTT标识和多余空行 NSMutableString *cleanedContent = [NSMutableString stringWithString:webvttContent]; NSRange webvttRange = [cleanedContent rangeOfString:@"WEBVTT" options:NSCaseInsensitiveSearch]; if (webvttRange.location != NSNotFound) { // 移除WEBVTT标识及后续的换行符 [cleanedContent deleteCharactersInRange:NSMakeRange(webvttRange.location, webvttRange.length + 1)]; } // 移除开头的所有空行 while ([cleanedContent hasPrefix:@"\n"] || [cleanedContent hasPrefix:@"\r"]) { [cleanedContent deleteCharactersInRange:NSMakeRange(0, 1)]; } // 2. 按空行分割成单个字幕块 NSArray *subtitleBlocks = [cleanedContent componentsSeparatedByString:@"\n\n"]; NSMutableArray *srtBlocks = [NSMutableArray array]; NSInteger currentIndex = 1; // 用于自动生成序号的计数器 for (NSString *block in subtitleBlocks) { if (block.length == 0) continue; NSMutableString *srtBlock = [NSMutableString string]; // 分割块内的行,过滤空行 NSArray *lines = [block componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]; lines = [lines filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]]; if (lines.count < 2) continue; // 无效块:至少需要时间线+内容 NSString *firstLine = lines[0]; NSInteger blockIndex = currentIndex; // 判断第一行是否为纯数字序号 NSCharacterSet *nonDigitSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; if ([firstLine rangeOfCharacterFromSet:nonDigitSet].location == NSNotFound) { blockIndex = [firstLine integerValue]; // 跳过序号行,处理剩下的内容 lines = [lines subarrayWithRange:NSMakeRange(1, lines.count - 1)]; } // 添加SRT序号 [srtBlock appendFormat:@"%ld\n", (long)blockIndex]; // 处理时间线:替换.为,,补全小时 NSString *timeLine = lines[0]; NSString *convertedTimeLine = [timeLine stringByReplacingOccurrencesOfString:@"." withString:@","]; // 如果时间线是MM:SS,mmm格式,补全小时为00: if ([convertedTimeLine componentsSeparatedByString:@":"].count == 2) { convertedTimeLine = [NSString stringWithFormat:@"00:%@", convertedTimeLine]; } [srtBlock appendFormat:@"%@\n", convertedTimeLine]; // 添加字幕内容(支持多行) NSArray *contentLines = [lines subarrayWithRange:NSMakeRange(1, lines.count - 1)]; [srtBlock appendString:[contentLines componentsJoinedByString:@"\n"]]; [srtBlocks addObject:srtBlock]; currentIndex = blockIndex + 1; } // 拼接所有SRT块,用空行分隔 return [srtBlocks componentsJoinedByString:@"\n\n"]; } @end
使用示例
你可以这样调用这个工具类来完成转换:
// 读取本地WEBVTT文件 NSString *webvttPath = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"vtt"]; NSError *error = nil; NSString *webvttContent = [NSString stringWithContentsOfFile:webvttPath encoding:NSUTF8StringEncoding error:&error]; if (error) { NSLog(@"读取WEBVTT文件失败:%@", error.localizedDescription); return; } // 转换为SRT格式 NSString *srtContent = [SubtitleConverter convertWEBVTTToSRT:webvttContent]; // 保存SRT文件到临时目录 NSString *srtPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"converted_sample.srt"]; [srtContent writeToFile:srtPath atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (!error) { NSLog(@"SRT文件已保存到:%@", srtPath); }
内容的提问来源于stack exchange,提问作者Ahd Radwan
相关产品推荐
相关产品推荐

