avsubtitleWriter demo解析(四):writeSubtitles上篇

来源:互联网 发布:淘宝客优惠券宣传海报 编辑:程序博客网 时间:2024/05/21 17:16

我已经预见到这部分会比较长,因此切分为上下两篇。


现在我们回到main函数调用void writeSubtitles(NSString *inputPath, NSString *outputPath, NSArray *subtitlesTextPaths)

首先从视频地址创建AVAsset,再创建对其的读取器AVAssetReader。这部分是为读取原视频信息做准备的。

NSError *error;// Setup the asset reader and writerAVAsset *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 writerNSMutableArray *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 movieNSMutableDictionary *assetWriterInputsCorrespondingToOriginalTrackIDs = [NSMutableDictionary dictionary];NSMutableArray *inputsOutputs = [NSMutableArray array];for (AVAssetTrack *track in asset.tracks){NSString *mediaType = track.mediaType;// Make the readerAVAssetReaderTrackOutput *trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:nil];[assetReader addOutput:trackOutput];// Make the writer input, using a source format hint if a format description is availableAVAssetWriterInput *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 codeinput.languageCode = track.languageCode;input.extendedLanguageTag = track.extendedLanguageTag;// Copy metadata from the asset track to the asset writer inputNSMutableArray *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 doif ([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 groupsassetWriterInputsCorrespondingToOriginalTrackIDs[@(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 codeinput.languageCode = track.languageCode;input.extendedLanguageTag = track.extendedLanguageTag;
拷贝language code和extendedLanguageTag
// Copy metadata from the asset track to the asset writer inputNSMutableArray *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 doif ([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 groupsassetWriterInputsCorrespondingToOriginalTrackIDs[@(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 tracksNSMutableArray *newSubtitlesInputs = [NSMutableArray array];NSMutableArray *subtitlesInputsOutputs = [NSMutableArray array];for (NSString *subtitlesPath in subtitlesTextPaths){// Read the contents of the subtitles fileNSString *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 readerSubtitlesTextReader *subtitlesTextReader = [SubtitlesTextReader subtitlesTextReaderWithText:text];// Make the writer input, using a source format hint if a format description is availableAVAssetWriterInput *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");}}

上篇先到这儿,有些内容以后补充。

0 0
原创粉丝点击