avsubtitleWriter demo解析(四):writeSubtitles上篇
2014-04-13 09:26
375 查看
我已经预见到这部分会比较长,因此切分为上下两篇。
现在我们回到main函数调用void writeSubtitles(NSString *inputPath, NSString *outputPath, NSArray *subtitlesTextPaths)
首先从视频地址创建AVAsset,再创建对其的读取器AVAssetReader。这部分是为读取原视频信息做准备的。
同样地,根据输出地址创建AVAsset和对应的写入器AVAssetWriter。这部分是为写入新视频做准备的。
接着,拷贝原视频的metaData给写入器
这边的思路是枚举asset的metadataFormats,这里返回NSString,再根据这个NSString获取AVMetadataItem。
接着将原视频里的track读出作为写入的源。
读取很简单,只要将track传给AVAssetReaderTrackOutput就行,这个便利构造器,产生一个AVAssetReaderTrackOutput。
写入有点麻烦,要将track的MediaType,sourceFormatHint也就是track的格式描述传给AVAssetWriterInput。这里我们只是构造了一下,还没add给写入器,因为我们的准备工作还没做完。
还要拷贝track的metaData
可以将input add到写入器了
接着为字幕构造input
上篇先到这儿,有些内容以后补充。
现在我们回到main函数调用void writeSubtitles(NSString *inputPath, NSString *outputPath, NSArray *subtitlesTextPaths)
首先从视频地址创建AVAsset,再创建对其的读取器AVAssetReader。这部分是为读取原视频信息做准备的。
NSError *error; // Setup the asset reader and writer AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:[inputPath stringByExpandingTildeInPath]]]; AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:asset error:&error]; if (error) { NSLog(@"error creating asset reader. exiting: %@", error); return; }
同样地,根据输出地址创建AVAsset和对应的写入器AVAssetWriter。这部分是为写入新视频做准备的。
NSURL *outputURL = [NSURL fileURLWithPath:[outputPath stringByExpandingTildeInPath]]; AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:outputURL fileType:AVFileTypeQuickTimeMovie error:&error]; if (error) { NSLog(@"error creating asset writer. exiting: %@", error); return; }
接着,拷贝原视频的metaData给写入器
// Copy metadata from the asset to the asset writer NSMutableArray *assetMetadata = [NSMutableArray array]; for (NSString *metadataFormat in asset.availableMetadataFormats) [assetMetadata addObjectsFromArray:[asset metadataForFormat:metadataFormat]]; assetWriter.metadata = assetMetadata; assetWriter.shouldOptimizeForNetworkUse = YES;
这边的思路是枚举asset的metadataFormats,这里返回NSString,再根据这个NSString获取AVMetadataItem。
接着将原视频里的track读出作为写入的源。
// Build up inputs and outputs for the reader and writer to carry over the tracks from the input movie into the new movie NSMutableDictionary *assetWriterInputsCorrespondingToOriginalTrackIDs = [NSMutableDictionary dictionary]; NSMutableArray *inputsOutputs = [NSMutableArray array]; for (AVAssetTrack *track in asset.tracks) { NSString *mediaType = track.mediaType; // Make the reader AVAssetReaderTrackOutput *trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:nil]; [assetReader addOutput:trackOutput]; // Make the writer input, using a source format hint if a format description is available AVAssetWriterInput *input; CMFormatDescriptionRef formatDescription = CFBridgingRetain([track.formatDescriptions firstObject]); if (formatDescription) { input = [AVAssetWriterInput assetWriterInputWithMediaType:mediaType outputSettings:nil sourceFormatHint:formatDescription]; CFRelease(formatDescription); } else { NSLog(@"skipping track on the assumption that there is no media data to carry over"); continue; } // Carry over language code input.languageCode = track.languageCode; input.extendedLanguageTag = track.extendedLanguageTag; // Copy metadata from the asset track to the asset writer input NSMutableArray *trackMetadata = [NSMutableArray array]; for (NSString *metadataFormat in track.availableMetadataFormats) [trackMetadata addObjectsFromArray:[track metadataForFormat:metadataFormat]]; input.metadata = trackMetadata; // Add the input, if that's okay to do if ([assetWriter canAddInput:input]) { [assetWriter addInput:input]; // Store the input and output to be used later when actually writing out the new movie [inputsOutputs addObject:@{@"input" : input, @"output" : trackOutput}]; // Track inputs corresponsing to track IDs for later preservation of track groups assetWriterInputsCorrespondingToOriginalTrackIDs[@(track.trackID)] = input; } else { NSLog(@"skipping input because it cannot be added to the asset writer"); } }
读取很简单,只要将track传给AVAssetReaderTrackOutput就行,这个便利构造器,产生一个AVAssetReaderTrackOutput。
写入有点麻烦,要将track的MediaType,sourceFormatHint也就是track的格式描述传给AVAssetWriterInput。这里我们只是构造了一下,还没add给写入器,因为我们的准备工作还没做完。
// Carry over language code input.languageCode = track.languageCode; input.extendedLanguageTag = track.extendedLanguageTag;拷贝language code和extendedLanguageTag
// Copy metadata from the asset track to the asset writer input NSMutableArray *trackMetadata = [NSMutableArray array]; for (NSString *metadataFormat in track.availableMetadataFormats) [trackMetadata addObjectsFromArray:[track metadataForFormat:metadataFormat]]; input.metadata = trackMetadata;
还要拷贝track的metaData
可以将input add到写入器了
// Add the input, if that's okay to do if ([assetWriter canAddInput:input]) { [assetWriter addInput:input]; // Store the input and output to be used later when actually writing out the new movie [inputsOutputs addObject:@{@"input" : input, @"output" : trackOutput}]; // Track inputs corresponsing to track IDs for later preservation of track groups assetWriterInputsCorrespondingToOriginalTrackIDs[@(track.trackID)] = input; } else { NSLog(@"skipping input because it cannot be added to the asset writer"); }
接着为字幕构造input
// Setup the inputs and outputs for new subtitle tracks NSMutableArray *newSubtitlesInputs = [NSMutableArray array]; NSMutableArray *subtitlesInputsOutputs = [NSMutableArray array]; for (NSString *subtitlesPath in subtitlesTextPaths) { // Read the contents of the subtitles file NSString *text = [NSString stringWithContentsOfURL:[NSURL fileURLWithPath:subtitlesPath] encoding:NSUTF8StringEncoding error:&error]; if (!text) { NSLog(@"there was a problem reading a subtitles file: %@", error); continue; } // Make the subtitles reader SubtitlesTextReader *subtitlesTextReader = [SubtitlesTextReader subtitlesTextReaderWithText:text]; // Make the writer input, using a source format hint if a format description is available AVAssetWriterInput *subtitlesInput; CMFormatDescriptionRef formatDescription = [subtitlesTextReader copyFormatDescription]; if (formatDescription) { subtitlesInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeSubtitle outputSettings:nil sourceFormatHint:formatDescription]; CFRelease(formatDescription); } else { NSLog(@"skipping subtitles reader on the assumption that there is no media data to carry over"); continue; } subtitlesInput.languageCode = subtitlesTextReader.languageCode; subtitlesInput.extendedLanguageTag = subtitlesTextReader.extendedLanguageTag; subtitlesInput.metadata = subtitlesTextReader.metadata; if ([assetWriter canAddInput:subtitlesInput]) { [assetWriter addInput:subtitlesInput]; // Store the input and output to be used later when actually writing out the new movie [subtitlesInputsOutputs addObject:@{@"input" : subtitlesInput, @"output" : subtitlesTextReader}]; [newSubtitlesInputs addObject:subtitlesInput]; } else { NSLog(@"skipping subtitles input because it cannot be added to the asset writer"); } }
上篇先到这儿,有些内容以后补充。
相关文章推荐
- avsubtitleWriter demo解析(二):创建CMSampleBufferRef
- avsubtitleWriter demo解析(三):SubtitlesTextReader
- avsubtitleWriter demo解析(四):writeSubtitles下篇
- avsubtitleWriter demo解析(一):字幕解析
- 避免主线程访问网络操作UI以及解析XMLDemo
- OMAPL138学习----DSPLINK DEMO解析之LOOP
- Android ApiDemos示例解析(10):App->Activity->QuickContactsDemo
- 用js对table进行解析的demo,及用js修改table中文字颜色
- Android笔记 解析xml文件demo
- Android~AsyncTask异步操作DEMO学习解析
- LUA解析json小demo
- Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)(源码 + Demo)
- 对组织架构xml文件orgdemo.xml进行解析
- 【Android 源码解析】bus 实现原理(附demo)
- Android ApiDemo解析-AnimationCloning类
- iOS开发- 以图搜图功能实现 (demo+解析)
- Java使用Dom方式解析xml文件Demo
- AVFoundation + AssetWriter: Generate Movie With Images and Audio
- 图片上传转base64预览demo及个人解析
- OpenRTMFP/Cumulus Primer(9)AMF解析之BinaryReader/Writer