2

CoreAudio に関する本を 1 冊丸ごと読む前に、それが自分にとって最適なフレームワークであるかどうか、または AVFoundation が必要なことを実行できるかどうかを知りたいと思いました。リモートサーバーにあるMP3のごく一部、たとえば20秒のファイルをダウンロードできるようにしたいのですが、最初にファイル全体をダウンロードしてからトリミングする必要はありません。

次に、オーディオの 2 つのトラックをレイヤー化し、それらを 1 つのファイルとしてバウンスします。

CoreAudio を掘り下げる必要がありますか、それとも AVFoundation で解決できますか? アドバイスは大歓迎です。

4

1 に答える 1

2

ファイルのダウンロード部分はあなた次第ですが、2 つ以上のオーディオ ファイルを 1 つにミックスしたい場合は、AVFoundation を使用AVAssetExportSessionしてエクスポートAVMutableAudioMixを行い、ミックスを行うのがおそらく最も簡単な方法です。いくつかの例があります。アップルのドキュメントに出回っている単純なエディターのコードですが、見つけられないようです。もしそうなら、リンクを投稿します..

これは実際にミックスを行うメソッドです。ここでもビデオを追加していることに注意してください。_audioTracks と _videoTracks は、AVAssets を含む可変配列です。

-(void)createMix
{

    CGSize videoSize = [[_videoTracks objectAtIndex:0] naturalSize];
    AVMutableComposition *composition = [AVMutableComposition composition];
    AVMutableVideoComposition *videoComposition = nil;
    AVMutableAudioMix *audioMix = nil;

    composition.naturalSize = videoSize;


    AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];



    AVAsset *videoAsset=[_videoTracks objectAtIndex:0];
   CMTimeRange  timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]);
        AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
        [compositionVideoTrack insertTimeRange:timeRangeInAsset ofTrack:clipVideoTrack atTime:kCMTimeZero error:nil];

        AVAssetTrack *clipAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
        [compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];


    NSMutableArray *trackMixArray = [NSMutableArray array];

    if(_audioTracks && _audioTracks.count>0)
    {
        for(AVAsset *audio in _audioTracks)
        {
          //     CMTimeRange  timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [audio duration]);
           // AVAssetTrack *clipAudioTrack = [[audio tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
            //[compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];


            NSInteger i;
            NSArray *tracksToDuck = [audio tracksWithMediaType:AVMediaTypeAudio]; // before we add the commentary

            // Clip commentary duration to composition duration.
            CMTimeRange commentaryTimeRange = CMTimeRangeMake(kCMTimeZero, audio.duration);
            if (CMTIME_COMPARE_INLINE(CMTimeRangeGetEnd(commentaryTimeRange), >, [composition duration]))
                commentaryTimeRange.duration = CMTimeSubtract([composition duration], commentaryTimeRange.start);

            // Add the commentary track.
            AVMutableCompositionTrack *compositionCommentaryTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
            [compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, commentaryTimeRange.duration) ofTrack:[[audio tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:commentaryTimeRange.start error:nil];



            CMTime rampDuration = CMTimeMake(1, 2); // half-second ramps
            for (i = 0; i < [tracksToDuck count]; i++) {
                AVMutableAudioMixInputParameters *trackMix = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:[tracksToDuck objectAtIndex:i]];
                [trackMix setVolumeRampFromStartVolume:1.0 toEndVolume:0.2 timeRange:CMTimeRangeMake(CMTimeSubtract(commentaryTimeRange.start, rampDuration), rampDuration)];
                [trackMix setVolumeRampFromStartVolume:0.2 toEndVolume:1.0 timeRange:CMTimeRangeMake(CMTimeRangeGetEnd(commentaryTimeRange), rampDuration)];
                [trackMixArray addObject:trackMix];

            }


        }
    }

     // audioMix.inputParameters = trackMixArray;

    if (videoComposition) {
        // Every videoComposition needs these properties to be set:
        videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps
        videoComposition.renderSize = videoSize;
    }


    AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPreset1280x720];
    session.videoComposition = videoComposition;
    session.audioMix = audioMix;

    NSUInteger count = 0;
    NSString *filePath;
    do {
        filePath = NSTemporaryDirectory();

        NSString *numberString = count > 0 ? [NSString stringWithFormat:@"-%i", count] : @"";
        filePath = [filePath stringByAppendingPathComponent:[NSString stringWithFormat:@"Output-%@.mp4", numberString]];
        count++;
    } while([[NSFileManager defaultManager] fileExistsAtPath:filePath]);      

    session.outputURL = [NSURL fileURLWithPath:filePath];
    session.outputFileType = AVFileTypeQuickTimeMovie;

     [session exportAsynchronouslyWithCompletionHandler:^
     {
         dispatch_async(dispatch_get_main_queue(), ^{
             NSLog(@"Exported");
             if(session.error)
             {
                 NSLog(@"had an error %@", session.error);
             }
             if(delegate && [delegate respondsToSelector:@selector(didFinishExportingMovie:)])
             {
                 [delegate didFinishExportingMovie:filePath];
             }


     });
     }];



}

それが役に立てば幸い..

ダニエル

于 2012-08-23T15:43:59.357 に答える