Подтвердить что ты не робот

AVPlayer seekToTime не воспроизводится в правильном положении

У меня есть AVPlayer, который воспроизводит видеопоток HLS. Мой пользовательский интерфейс предоставляет ряд кнопок, по одному для каждой "главы" в видео (кнопки обозначены "1", "2", "3" ). Приложение загружает некоторые метаданные с сервера, который содержит список точек отсечки главы, обозначенных в секундах. Например, одно видео длится 12 минут - список точек отсечки главы - 0, 58, 71, 230, 530 и т.д. И т.д.

Когда пользователь нажимает одну из "кнопок главы", код обработчика кнопок делает это:

            [self.avPlayer pause];

    [self.avPlayer seekToTime: CMTimeMakeWithSeconds(seekTime, 600) 
              toleranceBefore: kCMTimeZero 
               toleranceAfter: kCMTimeZero 
            completionHandler: ^(BOOL finished) 
            {
                [self.avPlayer play];
            }];

Где "seekTime" - это локальный var, который содержит точку разреза (как описано выше).

Проблема заключается в том, что видео не всегда начинается с правильной точки. Иногда это происходит. Но иногда это от десятой до секунды, до 2 секунд до запрошенного времени поиска. Он НИКОГДА не запускается после запрошенного времени поиска.

Вот некоторые данные о кодировании видео:

Кодировщик: handbrakeCLI Кодек: h.264 Частота кадров: 24 (на самом деле, 23,976 - то же, что и для съемки) Битрейт видео: несколько битрейтов (64/150/300/500/800/1200) Битрейт аудио: 128k Ключевые фреймы: 23.976 (1 в секунду)

Я использую средство Apple mediafilesegmenter, конечно, и файл variantplaylist для создания списка воспроизведения.

Файлы подаются из ведра Amazon Cloud/S3.

Одна из областей, о которой я остаюсь неясной, - это CMTimeMakeWithSeconds. Я пробовал несколько вариантов, основанных на разных статьях/документах, которые я прочитал. Например, в приведенном выше отрывке я использую:

CMTimeMakeWithSeconds (seekTime, 600)

Я также пробовал:

CMTimeMakeWithSeconds (seekTime, 1)

Я не могу сказать, что правильно, хотя BOTH, похоже, выдает те же несогласованные результаты!

Я также пробовал:

CMTimeMakeWithSeconds (seekTime, 23.967)

Некоторые статьи утверждают, что это работает как числитель/деноментор, поэтому n/1 должно быть правильным, где "n" - количество секунд (как в CMTimeMakeWithseconds (n, 1)). Но код изначально был создан другим программистом (который сейчас ушел), и он использовал номер 600 для предпочтительногоTimeScale (т.е. CMTimeMakeWithseconds (n, 600)).

Может ли кто-нибудь подсказывать, что я делаю неправильно, или даже если точность, которую я пытаюсь достичь, даже возможна?

И в случае, если у кого-то возникает соблазн предложить "альтернативные" решения, мы уже рассматриваем возможность разбить видео на отдельные потоки, по одной на главу, но мы не считаем, что это даст нам такую ​​же производительность в том смысле, что изменение глав займет больше времени, так как новый AVPlayerItem должен быть создан и загружен и т.д. и т.д. и т.д. Поэтому, если вы считаете, что это единственное решение, которое будет работать (и мы ожидаем, что это достигнет желаемого результата, т.е. каждая глава начнет именно там, где мы хотим), не стесняйтесь сказать это.

Спасибо заранее!

4b9b3361

Ответ 1

int32_t timeScale = self.player.currentItem.asset.duration.timescale;
CMTime time = CMTimeMakeWithSeconds(77.000000, timeScale);
[self.player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];

У меня возникла проблема с 'seekToTime'. Я решил проблему с этим кодом. "timescale" - это трюк для этой проблемы.

Ответ 2

Мое предложение: 1) Не используйте [avplayer seekToTime: toleranceBefore: toleranceAfter:], это задержит ваше время поиска 4-5 секунд.

2) Видео HLS сокращается до 10 секунд на сегмент. Начальная позиция главы должна соответствовать значению, которое умножается на 10. Поскольку сегмент начинается с кадра I, таким образом вы можете быстро найти время и точное время.

Ответ 3

используйте функцию как [player seekToTime:CMTimeMakeWithSeconds(seekTime,1)].
Поскольку ваше значение допуска kCMTimeZero займет больше времени, чтобы искать. Вместо использования значения допуска kCMTimeZero вы можете использовать kCMTimeIndefinite, что эквивалентно функции, указанной мной ранее.

Ответ 4

Поместите этот код, это может решить вашу проблему.

let targetTime = CMTimeMakeWithSeconds(videoLastDuration, 1) // videoLastDuration hold the previous video state.
self.playerController.player?.currentItem?.seekToTime(targetTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)