Лучший способ воспроизвести тишину с помощью AVAudioPlayer на iOS

Я оказался в ситуации, когда мне нужно имитировать воспроизведение звука, чтобы обмануть элементы управления ОС и MPNowPlayingInfoCenter заставить думать, что звук воспроизводится. Это связано с тем, что я создаю проигрыватель, который воспроизводит несколько звуковых дорожек с паузами между ними для создания одной непрерывной звуковой дорожки. У меня уже все настроено внутри самого приложения, и элементы управления экрана блокировки работают правильно, но единственная проблема, с которой я сталкиваюсь, заключается в том, что фактический звук останавливается и воспроизводится пауза, информационный центр экрана блокировки останавливает таймер, и это только продолжает показывать правильное время и общее состояние, как только начинается воспроизведение другой звуковой дорожки.

Вот пример моей звуковой дорожки, построенной из аудиофайлов и элементов паузы:

let items: [AudioItem] = [
    .audio("part-1.mp3"),
    .pause(duration: 5), // value of type: TimeInterval
    .audio("part-2.mp3"),
    .pause(duration: 3),
    ... // the list goes on
]

затем в моем пользовательском проигрывателе, как только AVAudioPlayer завершает свою работу с текущим элементом, я получаю следующий из массива и играю либо .pause с запланированным Timer, либо другой .audio с AVAudioPlayer.

extension Player: AVAudioPlayerDelegate {
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        playNextItem()
    }
}

И вот в чем проблема: как только AVAudioPlayer останавливается, информационный центр «Исполняется» автоматически останавливается, даже если я продолжаю кормить его свежим nowPlayingInfo. Затем, когда он попадает в другой элемент .audio, он корректно возобновляется и показывает текущее время и т. д.

А вот и вопрос

как мне обмануть MPNowPlayingInfoCenter, чтобы он подумал, что звук воспроизводится, когда я играю на своем .pause элементе?

Я понимаю, что может быть все еще неясно, чего я пытаюсь достичь, но я рад поделиться более подробной информацией, если это необходимо. Спасибо!

Некоторые решения, о которых я сейчас думаю:

A. Сохранение пустой звуковой дорожки длиной 1 с, которая будет воспроизводиться в цикле до тех пор, пока для воспроизведения требуется пауза.

B. Создание программно пустой звуковой дорожки соответствующей длины и ее воспроизведение вместо использования Timer для отслеживания продолжительности/прогресса паузы и полного использования AVAudioPlayer для элементов .audio и .pause. Хотя не уверен, что это возможно.

C. Может быть, есть способ сообщить MPNowPlayingInfoCenter, что звук продолжает воспроизводиться, без необходимости использования AVAudioPlayer, но какого-то API, с которым я не знаком?


person Witek Bobrowski    schedule 02.12.2020    source источник


Ответы (1)


AVAudioPlayer, вероятно, здесь неправильный инструмент. Вам нужен AVAudioPlayerNode, который немного ниже уровня. Создайте AVAudioEngine и прикрепите AVAudioPlayerNode. Затем вы можете вызвать scheduleFile(_:at:completionHandler:) для воспроизведения звука в нужное вам время.

Большая часть документации Apple на AVAudioEngine в данный момент выглядит неработающей, но мы надеемся, что ссылки будут скоро будет снова доступен по ссылкам для блоков звукового движка. (Если он не работает и у вас возникли проблемы с поиском документов, оставьте комментарий, и я найду видео WWDC и другие руководства по использованию AVAudioEngine. Это не особенно сложно для простых задач.)

Если вы заранее знаете, как вы хотите скомпоновать эти элементы (а похоже, что можете), см. также AVMutableComposition, который позволяет очень эффективно склеивать ресурсы, включая добавление пустых сегментов тишины. См. композицию и редактирование мультимедиа, чтобы узнать о различных инструментах в этой области.

person Rob Napier    schedule 02.12.2020
comment
спасибо за этот ответ! Я посмотрю на эти ссылки и отвечу вам, как только у меня будет какой-то результат. - person Witek Bobrowski; 02.12.2020
comment
Я заново реализовал все это с помощью AVMutableComposition, и все работает, как и ожидалось! Большое спасибо. - person Witek Bobrowski; 03.12.2020