2

たくさんのビデオをつなぎ合わせてから、iOS でビデオに音楽を追加しようとしています。を使用してオーディオを追加しAVMutableAudioMixます。ただし、ビデオが最終的にエクスポートされると、オーディオ ミックスが失われます。コードは次のようになります。

- (void)mergeVideos:(NSArray *)videos{
    AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
    AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];
    CMTime currentTime = kCMTimeZero;
    for (AVAsset *asset in videos) {
        // 2 - Video track
        [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
                            ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:currentTime error:nil];
        [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
                            ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:currentTime error:nil];
        currentTime = CMTimeAdd(currentTime, asset.duration);
    }
        // 4 - Get path
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:
                             [NSString stringWithFormat:@"mergeVideo-%d.mp4",arc4random() % 1000]];
    NSURL *url = [NSURL fileURLWithPath:myPathDocs]; 
    // 5 - Create exporter
    NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:mixComposition];
    NSString *quality = AVAssetExportPresetHighestQuality;
    //load the audio
    AVMutableAudioMix *audioMix = nil;
    NSURL *audioURL = [self loadAudioFile];// gives a url for a .caf file from the bundle
    if (audioURL) {
        AVURLAsset *audioAsset = [AVURLAsset assetWithURL:audioURL];
        AVAssetTrack *aTrack =  (AVAssetTrack *)[[audioAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];

        AVMutableAudioMixInputParameters *trackMix =
        [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:aTrack];

        [trackMix setVolumeRampFromStartVolume:0 toEndVolume:1 timeRange:
         CMTimeRangeMake(CMTimeMakeWithSeconds(0, 1), CMTimeMakeWithSeconds(3, 1))];
        [trackMix setVolume:1.0 atTime:kCMTimeZero];
        AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
        audioMix.inputParameters = [NSArray arrayWithObject:trackMix];
    }

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                      presetName:quality];
    if (audioMix) {
        exporter.audioMix = audioMix;
    }
    exporter.outputURL=url;
    exporter.outputFileType = AVFileTypeMPEG4;
    exporter.shouldOptimizeForNetworkUse = YES;
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self exportDidFinish:exporter];
        });
    }];
}

実行時にエラーはありません。ファイルに含まれる音楽.cafがエクスポートされたファイルにミックスされないということだけです。何が起こっているのですか?

4

1 に答える 1

3

You haven't inserted the audio from the .caf file into any AVMutableCompositionTrack, so the audio mix associated with aTrack is not going to adjust the volume for the .caf file. If you'd like the audio from the .caf file to be included in the video with the associated audio mix, create another AVMutableCompositionTrack to hold the audio from the .caf file:

AVMutableCompositionTrack *audioTrackCAF = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                    preferredTrackID:kCMPersistentTrackID_Invalid];

(with the time ranges set to your liking):

[audioTrackCAF insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration)
                            ofTrack:aTrack atTime:kCMTimeZero error:nil]

Additionally, is helpful to pass an NSError * (instead of nil) to insertTimeRange:ofTrack:atTime:error to make sure you had valid time ranges and your media was inserted.

于 2013-10-10T14:02:14.707 に答える