Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scaleTimeRange has no effect on audio type AVMutableCompositionTrack

I am working on a simple video editing app. I want to add slow motion to my app. I notice there is a scaleTimeRange method in the AVMutableCompositionTrack class, so I use it to achieve my purpose. I found scaleTimeRange works very well on video track, but has no any effect on audio track. This means the audio track still plays in original speed.

Follow is my code:

    CMTime insertionPoint = kCMTimeZero;

    double wholeDuration = CMTimeGetSeconds([asset duration]);
    double doubleDuration = CMTimeGetSeconds([asset duration])*2.0;
    CMTime trimmedDuration = CMTimeMakeWithSeconds(wholeDuration, 600.0);

    // Create a new composition
    self.mutableComposition = [AVMutableComposition composition];

    // Insert video and audio tracks from AVAsset
    if(assetVideoTrack != nil) {
        AVMutableCompositionTrack *compositionVideoTrack = [self.mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
        [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, trimmedDuration) ofTrack:assetVideoTrack atTime:insertionPoint error:&error];

        [compositionVideoTrack scaleTimeRange:CMTimeRangeMake(kCMTimeZero, trimmedDuration) toDuration:CMTimeMakeWithSeconds(doubleDuration, 600.0)];
    }
    if(assetAudioTrack != nil) {
        AVMutableCompositionTrack *compositionAudioTrack = [self.mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
        [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, trimmedDuration) ofTrack:assetAudioTrack atTime:insertionPoint error:&error];

        [compositionAudioTrack scaleTimeRange:CMTimeRangeMake(kCMTimeZero, trimmedDuration) toDuration:CMTimeMakeWithSeconds(doubleDuration, 600.0)];
    }

Can anyone give me some advice about the problem? Thank you!

like image 294
topfortune Avatar asked Jun 24 '13 06:06

topfortune


2 Answers

To be able to play slow mo with sound just set appropriate audioTimePitchAlgorithm for AVPlayerItem

playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmVarispeed;
like image 141
Mupinc Avatar answered Nov 19 '22 15:11

Mupinc


ScaleTimeRange does not work for audio due to a bug in apple api (Bug ID : 14616144). However, time scaling audio could be done using resampling. If audio is sampled at 48 kHz, resample to 96 kHz and play the audio at 48 kHz this will take twice as long to play. Generally:

scaledSampleRate = (orignalSampleRate / playRate);
playRate = (originalSampleRate / scaledSampleRate);

The pitch will be lowered though, if this is not desired. The solution might be a third party api. If you can extract the audio to a separate player i guess you could use AVAudioPlayer, where you can set the play-rate:

player = [[AVAudioPlayer alloc] initWithContentsOfURL:
                  [NSURL fileURLWithPath:path] error:&err];
        player.volume = 0.4f;
        player.enableRate=YES;
        [player prepareToPlay];
        [player setNumberOfLoops:0];
        player.rate=2.0f;
        [player play];
like image 33
David Karlsson Avatar answered Nov 19 '22 15:11

David Karlsson