iosavplayeravmutablecompositionavplayerlooper

AVPlayerLooper, AVComposition with AVMutableAudioMixInputParameters : volume is instable between loops


I use a AVPlayerLooper to loop a video inside an AVPlayer. The video is actually an AVComposition merging two audio tracks and one video track.

I apply two audiomix input parameters on the composition, one for each audio track to manage their respective volume (using setVolume() method). Note also that one of the audio track has also a tap processor to apply some audio filters, using the dedicated property inside the audiomix input parameter.

Everything seems to work fine but I noticed an issue with the volume:

The first loop is fine and render the expected volume, but the volume of the next loops seems to be random, one loop being at the expected volume (let’s say 4.0 in setVolume()), the other being at default (1.0).

Note that if I mute and unmute the AVPlayer while playing in a loop where the volume is lower than expected, the volume comes back to its configured and expected value.

Note that exporting the same composition in a file (so out of any looper) with AVAssetExportSession is working great, the volume is always as expected.

Have you got any tips to help me with this issue?


Solution

  • Everything about this sounds like a bug (viz first loop works, AVAssetExportSession works), plus setting the volume of AVMutableAudioMixInputParameters to values outside of the documented [0, 1] range sounds like the kind of thing that could provoke weird behaviour, HOWEVER changing the MTAudioProcessingTap creation flags from kMTAudioProcessingTapCreationFlag_PostEffects to kMTAudioProcessingTapCreationFlag_PreEffects seems to fix or at least work around this problem.

    From the header file:

    kMTAudioProcessingTapCreationFlag_PreEffects Signifies that the processing tap is inserted before any effects.
    kMTAudioProcessingTapCreationFlag_PostEffects Signifies that the processing tap is inserted after any effects.

    My reading of this is that the two flags only change who gets first bite at the audio: the tap or the AVAudioMix inputParameters (inputParameters don't get special precedence flags so I assume they are applied in array order?). Nothing about all this suggests that mix configuration is thrown away at a certain point in time, so I guess pre-fx just happens to let you avoid the buggy, unhappy code path.

    So in summary, I hope that it's not a problem for you to apply volume control after your tap. If it is, just apply the volume yourself inside your tap.

    But, man, a nasty interaction between AVPlayerLooper, AVComposition and MTAudioProcessingTap? Yikes. And flags are always a red flag in API design.