1
votes

I'm working on an app that allows you to merge photos and videos selected from the user's photo library into a single movie. So far, my app easily handles regular videos, Live Photos (as videos), and still photos. However, I'm having lots of trouble with slow motion videos (and time lapses, for that matter).

My main problem is: the audio in the slow motion segment of a slow-mo video is extremely distorted (like, it sounds sort of buzzy and robotic and choppy). The video appears as it should.

From the answers to this question, I decided to first export a slow motion video's AVComposition to the temporary directory using AVAssetExportSession and the highest quality preset and then use the resulting file to create an AVURLAsset for use in my composition. I can confirm that this initially exported video also has the audio distortion. All I'm doing is trying to export the AVAsset I've fetched from the PHAsset without any changes.

My question is: how can I take a slow motion video from the user's library and export it to a temporary directory as an .mov file so that it plays as expected, with the slow motion segment's audio correctly pitch shifted without extreme distortion?

Does AVAssetExportSession just not handle this right? Should I use AVAssetWriter instead? I'm not sure posting any code would help as all I'm doing is setting up a temp directory path and an AVAssetExportSession to export the AVComposition, which succeeds.

My app is written is Swift, but I'll take answers in Objective C.

1

1 Answers

5
votes

I've been having similar problems with an app of mine, applying filters to video selected from the library and then exporting them. As you say, audio on slo mo videos was harshly distorted. I think I've found the solution for my case, hope it helps with yours.

TLDR Check the audioTimePitchAlgorithm on any AVPlayers in your app but particularly on any instance of AVAssetExportSession - make sure it is set to .varispeed

As per the documentation the default for audioTimePitchAlgorithm on any instance of AVPlayer or AVAssetExportSession is .spectral which is the highest quality but will maintain a constant pitch. I think the attempt to maintain a constant pitch in slo mo video is producing the unwanted distortion effects. Switching to .varispeed produces exported video as expected, with pitch shifted audio.

Here is my code for instantiating an AVAssetExportSession for this puropose:

    let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: asset)
    var preset: String = AVAssetExportPresetPassthrough
    if compatiblePresets.contains(outputQuality) { preset = outputQuality }
    let session = AVAssetExportSession.init(asset: asset, presetName: preset)
    session?.audioTimePitchAlgorithm = **.varispeed**

Hope this helps,

Pete