您的位置:首页 > 其它

avsubtitleWriter demo解析(四):writeSubtitles上篇

2014-04-13 09:26 375 查看
我已经预见到这部分会比较长,因此切分为上下两篇。

现在我们回到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");
}
}


上篇先到这儿,有些内容以后补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: