2011-03-30 12 views
18

मैं AVAssetWriter के साथ एक फिल्म निर्यात करना चाहता हूं और यह समझ नहीं सकता कि वीडियो और ऑडियो ट्रैक को सिंक में कैसे शामिल किया जाए। केवल वीडियो निर्यात ठीक काम करता है, लेकिन जब मैं ऑडियो जोड़ने के परिणामस्वरूप फिल्म इस तरह दिखता है:AVAssetWriter का उपयोग कर वीडियो और ऑडियो के साथ एक मूवी कैसे लिखें?

सबसे पहले मैं वीडियो (ऑडियो के बिना) देखते हैं, तो वीडियो फ्रीज़ (अंत तक अंतिम छवि फ्रेम दिखा रहा है) और कुछ के बाद सेकंड मैं ऑडियो सुनता हूँ।

मैं CMSampleBufferSetOutputPresentationTimeStamp साथ कुछ बातें करने की कोशिश की ऑडियो के लिए (प्रथम CMSampleBufferGetPresentationTimeStamp वर्तमान से घटाकर), लेकिन यह सब काम नहीं किया और मुझे नहीं लगता कि यह सही दिशा है करते हैं, क्योंकि स्रोत में वीडियो & ऑडियो फिल्म सिंक किसी भी प्रकार से होना चाहिए ...

संक्षेप में मेरे सेटअप: मैं बनाने के एक AVAssetReader और 2 AVAssetReaderTrackOutput (वीडियो के लिए एक, ऑडियो के लिए एक) और उन्हें AVAssetReader में जोड़ने के लिए, तो मैं बनाने के एक AVAssetWriter और 2 AVAssetWriterInput (वीडियो & ऑडियो) और उन्हें AVAssetWriter पर जोड़ें ... मैं इसे सभी के साथ शुरू करता हूं:

[assetReader startReading]; 
[assetWriter startWriting]; 
[assetWriter startSessionAtSourceTime:kCMTimeZero]; 

तब मैं नमूना बफर सामान करने के लिए 2 कतारों चलाएँ:

dispatch_queue_t queueVideo=dispatch_queue_create("assetVideoWriterQueue", NULL); 
[assetWriterVideoInput requestMediaDataWhenReadyOnQueue:queueVideo usingBlock:^ 
{ 
    while([assetWriterVideoInput isReadyForMoreMediaData]) 
    { 
     CMSampleBufferRef sampleBuffer=[assetReaderVideoOutput copyNextSampleBuffer]; 
     if(sampleBuffer) 
     { 
      [assetWriterVideoInput appendSampleBuffer:sampleBuffer]; 
      CFRelease(sampleBuffer); 
     } else 
     { 
      [assetWriterVideoInput markAsFinished]; 
      dispatch_release(queueVideo); 
      videoFinished=YES; 
      break; 
     } 
    } 
}]; 

dispatch_queue_t queueAudio=dispatch_queue_create("assetAudioWriterQueue", NULL); 
[assetWriterAudioInput requestMediaDataWhenReadyOnQueue:queueAudio usingBlock:^ 
{ 
    while([assetWriterAudioInput isReadyForMoreMediaData]) 
    { 
     CMSampleBufferRef sampleBuffer=[assetReaderAudioOutput copyNextSampleBuffer]; 
     if(sampleBuffer) 
     { 
      [assetWriterAudioInput appendSampleBuffer:sampleBuffer]; 
      CFRelease(sampleBuffer); 
     } else 
     { 
      [assetWriterAudioInput markAsFinished]; 
      dispatch_release(queueAudio); 
      audioFinished=YES; 
      break; 
     } 
    } 
}]; 

मुख्य पाश मैं दोनों कतारों के लिए प्रतीक्षा में जब तक वे खत्म:

while(!videoFinished && !audioFinished) 
{ 
    sleep(1); 
} 
[assetWriter finishWriting]; 

इसके अलावा मैं करने की कोशिश निम्नलिखित कोड के साथ लाइब्रेरी में परिणामस्वरूप फ़ाइल को सहेजें ...

NSURL *url=[[NSURL alloc] initFileURLWithPath:path]; 
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
if([library videoAtPathIsCompatibleWithSavedPhotosAlbum:url]) 
{ 
    [library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error) 
    { 
     if(error) 
      NSLog(@"error=%@",error.localizedDescription); 
     else 
      NSLog(@"completed..."); 
    }]; 
} else 
    NSLog(@"error, video not saved..."); 

[library release]; 
[url release]; 
,210

... लेकिन मैं त्रुटि मिलती है:

Video /Users/cb/Library/Application Support/iPhone Simulator/4.2/Applications/E9865BF9-D190-4912-9248-66768B1AB635/Documents/export.mp4 cannot be saved to the saved photos album: Error Domain=NSOSStatusErrorDomain Code=-12950 "Movie could not be played." UserInfo=0x5e4fb90 {NSLocalizedDescription=Movie could not be played.}

कोड अन्य प्रोग्राम में समस्याओं के बिना काम करता है। तो फिल्म के साथ कुछ गलत है ...?

+0

मैंने ऑडियो फ़ाइल और एक चित्र सरणी से एक फिल्म बनाने के लिए स्टैक ओवरफ्लो पर एक पोस्ट लिखा था। शायद कोड का कुछ हिस्सा आपकी मदद कर सकता है। http://stackoverflow.com/questions/6061092/make-movie-file-with-picture-array-and-song-file-using-avasset – TheRonin

उत्तर

-3

यह लगता है कि propertyWriterAudioInput ऑडियो लेखन के लिए नमूना बफर समय को अनदेखा करता है। इस तरह से करें।

1) वीडियो ट्रैक लिखें।

2) जब पूरा हो जाए, तो इसे समाप्त करें i.e. [videoWriterInput markAsFinished];

3) [परिसंपत्तिवाटर प्रारंभ सत्रऑटसोर्सटाइम: टाइमरेंज स्टार्ट];

3) ऑडियो रीडर को तुरंत चालू करें और ऑडियो लिखना शुरू करें।

+0

startSessionAtSourceTime एक इनपुट के लिए नहीं, परिसंपत्ति लेखक के लिए है। इनपुट प्रबंधित करने के लिए इसका उपयोग करना असंभव है। – AlexeyVMP

9
-(void)mergeAudioVideo 
{ 

    NSString *videoOutputPath=[_documentsDirectory stringByAppendingPathComponent:@"dummy_video.mp4"]; 
    NSString *outputFilePath = [_documentsDirectory stringByAppendingPathComponent:@"final_video.mp4"]; 
    if ([[NSFileManager defaultManager]fileExistsAtPath:outputFilePath]) 
     [[NSFileManager defaultManager]removeItemAtPath:outputFilePath error:nil]; 


    NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath]; 
    NSString *filePath = [_documentsDirectory stringByAppendingPathComponent:@"newFile.m4a"]; 
    AVMutableComposition* mixComposition = [AVMutableComposition composition]; 

    NSURL *audio_inputFileUrl = [NSURL fileURLWithPath:filePath]; 
    NSURL *video_inputFileUrl = [NSURL fileURLWithPath:videoOutputPath]; 

    CMTime nextClipStartTime = kCMTimeZero; 

    AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:video_inputFileUrl options:nil]; 
    CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration); 

    AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:nextClipStartTime error:nil]; 

    AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:audio_inputFileUrl options:nil]; 
    CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration); 
    AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil]; 

    AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality]; 
    _assetExport.outputFileType = @"com.apple.quicktime-movie"; 
    _assetExport.outputURL = outputFileUrl; 

    [_assetExport exportAsynchronouslyWithCompletionHandler: 
    ^(void) { 
     if (_assetExport.status == AVAssetExportSessionStatusCompleted) { 

      //Write Code Here to Continue 
     } 
     else { 
      //Write Fail Code here  
     } 
    } 
    ]; 



} 

आप ऑडियो और वीडियो को मर्ज करने के लिए इस कोड का उपयोग कर सकते हैं।

संबंधित मुद्दे