AVAssetExportSession 音視頻的剪輯,以及格式的裝換

    //第一種方式
session

    

    //asset生成必須爲文件的url,並且是本地app

    AVAsset *mediaAsset = _player.currentItem.asset;異步

    

    //AVMutableComposition 能夠進行音視頻的組合ui

    

    AVAssetExportSession *es = [[AVAssetExportSession alloc] initWithAsset:mediaAsset presetName:AVAssetExportPresetPassthrough];url

    

    NSString *outPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"out.mov"];spa

    

    NSFileManager *fileManager = [NSFileManager defaultManager];.net

    [fileManager removeItemAtPath:outPath error:NULL];3d


    //格式的轉換orm

    es.outputFileType = AVFileTypeQuickTimeMovie;視頻

    es.outputURL = [[NSURL alloc] initFileURLWithPath:outPath];

    es.shouldOptimizeForNetworkUse=NO;

    CMTime start = CMTimeMakeWithSeconds(1.0, 600);

    CMTime duration = CMTimeMakeWithSeconds(3.0, 600);

    CMTimeRange range = CMTimeRangeMake(start, duration);

    //音頻的時間範圍

    es.timeRange = range;

    

    

    NSLog(@"exporting to %@",outPath);

    //異步輸出完成後調用

    [es exportAsynchronouslyWithCompletionHandler:^{

        NSString *status = @"" ;

        

        if( es.status == AVAssetExportSessionStatusCompleted ) status = @"AVAssetExportSessionStatusCompleted";

        else if( es.status == AVAssetExportSessionStatusFailed ) status = @"AVAssetExportSessionStatusFailed";

        

        

        NSLog(@"done exporting to %@ status %d = %@ (%@)",outPath,es.status, status,[es error]);

    }];

    

    

    //第二種方式讀取本地到另一個地方

    

    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    NSString *audioPath = [documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"audio"]];

    

    NSURL *fileUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/1141.mp3",audioPath]];

    

    

    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:fileUrl options:nil];

    NSError *error = nil;

    

    NSArray *array=[_player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio];

    

    AVAssetTrack *track=[[_player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio]firstObject];

    

    NSLog(@"%@",_player.currentItem.asset);

    

    assetReader=[[AVAssetReader alloc]initWithAsset:_player.currentItem.asset error:&error];

    NSDictionary *readerOutputSettings=@{(id)AVFormatIDKey:@(kAudioFormatLinearPCM)};

    

    //若是讀取失敗接下來的代碼不會執行。

    

    AVAssetReaderTrackOutput *trackOutput=[[AVAssetReaderTrackOutput alloc]initWithTrack:track outputSettings:readerOutputSettings];

    [assetReader addOutput:trackOutput];

    //先判斷readYES

    BOOL read= [assetReader startReading];

    

    

    NSString *userPath = [audioPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/writer1.wav"]];

    NSURL *outputURL=[NSURL fileURLWithPath:userPath];

    

    assetWriter=[[AVAssetWriter alloc]initWithURL:outputURL fileType:AVFileTypeWAVE error:nil];

    AudioChannelLayout channelLayout;

    memset(&channelLayout, 0, sizeof(AudioChannelLayout));

    channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

    

    //lin PCM須要設置PCM一些相關的屬性

    NSDictionary *writerOutputSetting=@{(id)AVFormatIDKey:@(kAudioFormatLinearPCM),(id)AVSampleRateKey:[NSNumber numberWithFloat:44100.0],AVNumberOfChannelsKey:[NSNumber numberWithInt: 2],AVLinearPCMBitDepthKey:[NSNumber numberWithInt:16],

                                        AVLinearPCMIsNonInterleaved:[NSNumber numberWithBool:NO],

                                        AVLinearPCMIsFloatKey:[NSNumber numberWithBool:NO],

                                        AVLinearPCMIsBigEndianKey:[NSNumber numberWithBool:NO],AVChannelLayoutKey:[ NSData dataWithBytes:&channelLayout length: sizeof( AudioChannelLayout ) ]};

    

    AVAssetWriterInput *writerInput=[[AVAssetWriterInput alloc]initWithMediaType:AVMediaTypeAudio outputSettings:writerOutputSetting];

    [assetWriter addInput:writerInput];

    BOOL writer=[assetWriter startWriting];

    

    

    dispatch_queue_t dispatchQueue=dispatch_queue_create("com/tapharmonic.WriterQueue", NULL);

    

    [assetWriter startSessionAtSourceTime:kCMTimeZero];

    [writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{

        

        bool complete=NO;

        while ([writerInput isReadyForMoreMediaData]&& !complete) {

            NSLog(@"%@",assetWriter.error);

            CMSampleBufferRef sampleBuffer=[trackOutput copyNextSampleBuffer];

            if(sampleBuffer){

                BOOL result=[writerInput appendSampleBuffer:sampleBuffer];

                CFRelease(sampleBuffer);

                complete=!result;

            }else{

                [writerInput markAsFinished];

                complete=YES;

            }

        }

        if(complete){

            [assetWriter finishWritingWithCompletionHandler:^{

                AVAssetWriterStatus status=assetWriter.status;

                NSLog(@"%@",assetWriter.error);

                if(status==AVAssetWriterStatusCompleted){

                    NSLog(@"AVAssetWriterStatusCompleted");

                }else{

                    NSLog(@"AVAssetWriterStatusFailed");

                }

            }];

        }

    }];


AVAssetExportSession你能夠取消這個生成操做,經過給session發送 cancelExport 消息。

失敗緣由:
· 若是導出的文件存在,或者導出的url在沙盒以外,這個導出操做會失敗。
· 來了一個電話
· 你的程序在後臺運行而且其餘的應用開始播放。
這種狀況下,你應該通知用戶export失敗,而且從新export。

相關文章
相關標籤/搜索