mp4 ファイルを異なる解像度で結合する必要がある iPad アプリをコーディングしています。そのために、AVAssetReader を組み合わせて mp4 ソース ファイルを読み取り、AVAssetWriter を使用してこれらのソース ファイルを単一の mp4 出力ファイルに書き込みます。
AVAssetExportSession を使用しようとしましたが、結合された異なるファイル間に黒いフレームがあったという問題がありました。
私が今直面している問題は、すべて問題ないように見えますが、AVAssetWriter の完了ハンドラーが呼び出されないことです。
これは、mp4 ファイル URL のリスト、単一の出力ファイル URL、および完了ハンドラーを入力として受け取るセレクターです。
- (void)resizeAndJoinVideosAtURLs:(NSArray *)videoURLs toOutputURL:(NSURL *)outputURL withHandler:(void(^)(NSURL *fileURL))handler
{
/*
First step: create the writer and writer input
*/
NSError *error = nil;
self.videoAssetWriter = [[AVAssetWriter alloc] initWithURL:outputURL fileType:AVFileTypeMPEG4 error:&error];
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,[NSNumber numberWithInt:640], AVVideoWidthKey,[NSNumber numberWithInt:480], AVVideoHeightKey,nil];
AVAssetWriterInput* videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
videoWriterInput.expectsMediaDataInRealTime = NO;
if([self.videoAssetWriter canAddInput:videoWriterInput])
{
[self.videoAssetWriter addInput:videoWriterInput];
[self.videoAssetWriter startWriting];
[self.videoAssetWriter startSessionAtSourceTime:kCMTimeZero];
/*
Second step: for each video URL given create a reader and an reader input
*/
for(NSURL *videoURL in videoURLs)
{
NSLog(@"Processing file: %@",videoURL);
AVAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
AVAssetReader *videoAssetReader = [[AVAssetReader alloc] initWithAsset:videoAsset error:&error];
AVAssetTrack *videoAssetTrack = [videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
NSDictionary *videoOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];
AVAssetReaderTrackOutput *videoAssetTrackOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:videoAssetTrack outputSettings:videoOptions];
videoAssetTrackOutput.alwaysCopiesSampleData = NO;
if([videoAssetReader canAddOutput:videoAssetTrackOutput])
{
[videoAssetReader addOutput:videoAssetTrackOutput];
[videoAssetReader startReading];
/*
Step three: copy the buffers from the reader to the writer
*/
while ([videoAssetReader status] == AVAssetReaderStatusReading)
{
if(![videoWriterInput isReadyForMoreMediaData]) continue;
CMSampleBufferRef buffer = [videoAssetTrackOutput copyNextSampleBuffer];
if(buffer)
{
[videoWriterInput appendSampleBuffer:buffer];
CFRelease(buffer);
}
}
} else NSLog(@"ERROR: %@",error);
}
[videoWriterInput markAsFinished];
} else NSLog(@"ERROR: %@",error);
__weak ClipBuilder *weakself = self;
[self.videoAssetWriter finishWritingWithCompletionHandler:^{
handler(outputURL);
weakself.videoAssetWriter = nil;
}];
}
私の出力ファイルは存在し、AVAssetWriter はプロパティであるため存在しますが、完了ハンドラーは呼び出されません。これを説明できるものは何ですか?
ご協力いただきありがとうございます。
それを説明できるものは何ですか?