1

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 はプロパティであるため存在しますが、完了ハンドラーは呼び出されません。これを説明できるものは何ですか?

ご協力いただきありがとうございます。

それを説明できるものは何ですか?

4

1 に答える 1