2013-11-26 11 views
6

से है। मैं .mov वीडियो को .mp4 में परिवर्तित करने की कोशिश कर रहा हूं और साथ ही उन्मुखीकरण को सही करता हूं। कोड मैं नीचे का उपयोग महान काम करता है जब एक वीडियो तथापि UIImagePickerController का उपयोग कर रिकॉर्डिंग वीडियो कैमरा रोल मैं इस त्रुटि मिलती है से चयन किया जाता है, तो और मैं देख रहा हूँ क्यों नहीं:AVAssetExportSession रोटेशन त्रुटि तब होती है जब वीडियो कैमरा रोल

निर्यात असफल: ऑपरेशन रूका: त्रुटि डोमेन = AVFoundationErrorDomain कोड = -11,841 "ऑपरेशन रूका" UserInfo = 0x1815ca50, {NSLocalizedDescription = कार्यवाही रोक दी, NSLocalizedFailureReason = वीडियो बना नहीं जा सका।}

मैं पहली बार एक और फाइल करने के लिए वीडियो को बचाने की कोशिश की है लेकिन इससे कोई फर्क नहीं पड़ता।

- (void)convertVideoToLowQuailtyAndFixRotationWithInputURL:(NSURL*)inputURL handler:(void (^)(NSURL *outURL))handler 
{ 
    if ([[inputURL pathExtension] isEqualToString:@"MOV"]) 
    { 
     NSURL *outputURL = [inputURL URLByDeletingPathExtension]; 
     outputURL = [outputURL URLByAppendingPathExtension:@"mp4"]; 

     AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil]; 

     AVAssetTrack *sourceVideoTrack = [[avAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
     AVAssetTrack *sourceAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 

     AVMutableComposition* composition = [AVMutableComposition composition]; 

     AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo 
                        preferredTrackID:kCMPersistentTrackID_Invalid]; 
     [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) 
             ofTrack:sourceVideoTrack 
             atTime:kCMTimeZero error:nil]; 
     [compositionVideoTrack setPreferredTransform:sourceVideoTrack.preferredTransform]; 

     AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio 
                        preferredTrackID:kCMPersistentTrackID_Invalid]; 
     [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) 
             ofTrack:sourceAudioTrack 
             atTime:kCMTimeZero error:nil]; 

     AVMutableVideoComposition *videoComposition = [self getVideoComposition:avAsset]; 

     NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset]; 
     if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality]) 
     { 
      AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:composition presetName:AVAssetExportPresetMediumQuality]; 
      exportSession.outputURL = outputURL; 
      exportSession.outputFileType = AVFileTypeMPEG4; 
      exportSession.shouldOptimizeForNetworkUse = YES; 
      exportSession.videoComposition = videoComposition; 
      [exportSession exportAsynchronouslyWithCompletionHandler:^{ 

       switch ([exportSession status]) 
       { 
        case AVAssetExportSessionStatusFailed: 
         NSLog(@"Export failed: %@ : %@", [[exportSession error] localizedDescription], [exportSession error]); 
         handler(nil); 

         break; 
        case AVAssetExportSessionStatusCancelled: 

         NSLog(@"Export canceled"); 
         handler(nil); 

         break; 
        default: 

         handler(outputURL); 

         break; 

       } 
      }]; 
     } 

    } else { 
     handler(inputURL); 
    } 
} 

- (AVMutableVideoComposition *)getVideoComposition:(AVAsset *)asset 
{ 
    AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    AVMutableComposition *composition = [AVMutableComposition composition]; 
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 
    CGSize videoSize = videoTrack.naturalSize; 
    BOOL isPortrait_ = [self isVideoPortrait:asset]; 
    if(isPortrait_) { 
//  NSLog(@"video is portrait "); 
     videoSize = CGSizeMake(videoSize.height, videoSize.width); 
    } 
    composition.naturalSize  = videoSize; 
    videoComposition.renderSize = videoSize; 
    videoComposition.frameDuration = CMTimeMakeWithSeconds(1/videoTrack.nominalFrameRate, 600); 

    AVMutableCompositionTrack *compositionVideoTrack; 
    compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:videoTrack atTime:kCMTimeZero error:nil]; 
    AVMutableVideoCompositionLayerInstruction *layerInst; 
    layerInst = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack]; 
    [layerInst setTransform:videoTrack.preferredTransform atTime:kCMTimeZero]; 
    AVMutableVideoCompositionInstruction *inst = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    inst.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration); 
    inst.layerInstructions = [NSArray arrayWithObject:layerInst]; 
    videoComposition.instructions = [NSArray arrayWithObject:inst]; 
    return videoComposition; 
} 

उत्तर

13

AVFoundation त्रुटि लगातार -11,841 मतलब है कि आप एक अवैध वीडियो रचना है:

यहाँ कोड मैं वीडियो कन्वर्ट करने के लिए उपयोग कर रहा हूँ है। यदि आप त्रुटि स्थिरांक पर अधिक जानकारी चाहते हैं तो यह लिंक देखें: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVFoundation_ErrorConstants/Reference/reference.html

हालांकि कोई भी बड़ी त्रुटि तुरंत मुझ पर नहीं आती है, तो मैं आपकी समस्या के स्रोत को कम करने के निम्नलिखित तरीकों का सुझाव दे सकता हूं।

पहले, बजाय इन कॉल में error पैरामीटर के लिए nil पास करने का:

[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) 
             ofTrack:sourceVideoTrack 
             atTime:kCMTimeZero error:nil]; 

एक NSError वस्तु बना सकते हैं और इसलिए है कि यह करने के लिए संदर्भ पारित:

NSError *error = nil; 
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) 
             ofTrack:sourceVideoTrack 
             atTime:kCMTimeZero error:&error]; 

त्रुटि की जांच करने के लिए सुनिश्चित करें कि आपके वीडियो और ऑडियो ट्रैक सही ढंग से रचना ट्रैक में डाले गए हैं। यदि सभी ठीक हो जाए तो त्रुटि nil होनी चाहिए।

if(error) 
    NSLog(@"Insertion error: %@", error); 

आप भी अपनी AVAsset के composable और exportable, और hasProtectedContent गुण की जाँच कर सकते हैं। यदि ये क्रमशः हाँ, हाँ, और नहीं हैं, तो आपको अपनी नई वीडियो फ़ाइल बनाने में समस्या हो सकती है।

कभी-कभी मैंने एक मुद्दा देखा है जहां एक ऑडियो ट्रैक के लिए समय सीमा बनाना एक वीडियो ट्रैक के साथ संयोजन में उपयोग किए जाने पर 600 गुना को पसंद नहीं करता है। आप केवल ऑडियो ट्रैक डालने के लिए

CMTimeRangeMake(kCMTimeZero, avAsset.duration) 

में अवधि (avAsset.duration) के लिए एक नया CMTime बनाना चाह सकते हैं। नए सीएमटाइम में, 44100 के एक टाइमकेल का उपयोग करें (या जो भी ऑडियो ट्रैक की नमूना दर है।) यह आपके videoComposition.frameDuration के लिए भी जाता है। आपके वीडियो ट्रैक के के आधार पर, आपका समय 600 बार-बार के साथ सही ढंग से प्रदर्शित नहीं किया जा सकता है।

अंत में, डिबग वीडियो रचनाओं के एप्पल द्वारा प्रदान की एक उपयोगी उपकरण है:

https://developer.apple.com/library/mac/samplecode/AVCompositionDebugViewer/Introduction/Intro.html

यह अपनी संरचना का एक दृश्य प्रतिनिधित्व देता है और जैसा कि आप देख सकते हैं, जहां चीजों की तरह उन्हें करना चाहिए मत देखो।

+0

अपने बहुत विस्तृत प्रतिक्रिया के लिए धन्यवाद। मैं अभी भी इसे काम नहीं कर सकता :( 'composable',' exportable' और 'संरक्षित सामग्री '4 जैसा आप कहते हैं। आपके पहले सुझाव से कोई त्रुटि वापस नहीं आई है। मैंने ऑडियो ट्रैक को 44,100 का उपयोग करने की कोशिश की। अगर मैं 'exportSession.videoComposition = videoComposition; पर टिप्पणी करता हूं, तो यह ठीक काम करता है हालांकि वीडियो घुमाया नहीं गया है। इसलिए समस्या कहीं और होनी चाहिए। धन्यवाद – Darren

+0

मुझे लगता है कि आप' - AVMutableVideoComposition * में 'AVMutableComposition') बनाते हैं। getVideoComposition', और उस से 'AVMutableCompositionTrack' बनाएं। हालांकि, '- (शून्य) में परिवर्तित करें VideoToLowQuailtyAndFixRotationWithInputURL: हैंडलर: ' , आपके पास _deifferent_' AVMutableComposition' है जिसे आप' AVExportSession' पर जा रहे हैं। इस रचना को पास करने के लिए VideoComposition AVMutableCompositionTracks को बनाने के लिए, इसलिए केवल एक ही है। – jlw

+0

मैं बस 'AVMutableVideoComposition' को 'AVMutableVideoCompositionLayerInstruction' के साथ मुख्य कन्वर्ट विधि में ले जाने का प्रयास किया, इसलिए इसमें केवल 1' AVMutableComposition' है लेकिन फिर भी वही परिणाम हैं। कैमरा रोल से वीडियो चुनते समय, इसे पार करने से पहले इसे संपीड़ित करता है, यह सुनिश्चित नहीं करता कि इससे कोई फर्क पड़ता है या नहीं। – Darren

2

नीचे लाइन टिप्पणी की कोशिश करो और आप निश्चित रूप से विधि isValidForAsset का उपयोग करना चाहिए अपनी परियोजना

exportSession.videoComposition = videoComposition; 
+0

के साथ सफलता यह मेरे लिए काम किया। धन्यवाद –

+2

यह म्यूटेबल वीडियो संरचना में जोड़े गए किसी भी ट्रांसफॉर्म, फसल इत्यादि को हटा देगा, इसलिए इस मामले में कोई उपयोग नहीं है। –

+0

यह मेरे लिए भी काम करता है। मैं उत्सुक हूँ हालांकि क्यों। क्या कोई जानता है? –

1

चलाएँ: timeRange: validationDelegate: AVVideoCompostion की है, यह किसी भी मुद्दे के लिए अपने वीडियो संरचना के साथ का निदान होगा। मैं एक ही समस्या थी और मेरे लिए समाधान मूल ट्रैक के बजाय AVMutableCompositionTrack साथ layerInstruction बनाने के लिए किया गया था:

layerInst = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack]; 
संबंधित मुद्दे