Каждый, кто хоть раз смотрел видео в интернете, понимает эту боль: видео запускается быстро, но в ужасном качестве. Или, наоборот, приходится по несколько секунд ждать, когда контент прогрузится сразу в высоком качестве. Как решить эту проблему, придумала команда онлайн-кинотеатра KION. О релизе новой функции и первых успехах рассказали продакт-менеджер Дмитрий Пискунов и разработчик Денис Чорный.

Суть проблемы

В стриминге есть актуальная и до сих пор толком не решенная проблема — как определить, в каком качестве начинать воспроизводить видео. Понятно, что благодаря адаптивному битрейту любой контент со временем подстроится: если есть возможность поднять качество, плеер это сделает. Но что делать на старте, какое качество выбрать?

Некоторые сервисы онлайн-кинотеатров сразу замахиваются на самое высокое качество. И потом зритель со слабым интернетом долго смотрит на «бублик» загрузки, ожидая начала воспроизведения.

Другие запускают видео с самого низкого качества вне зависимости от пропускной способности сети — и неприятно удивляют размазанной картинкой зрителей с хорошим интернет-сигналом. Если на мобильных гаджетах это еще не очень заметно, то на умных телевизорах сразу бросается в глаза.

До апреля этого года мы в KION стартовали с дефолтного качества — 480p. Но это решение не оптимально, оно не затрагивает крайности: тех, у кого очень медленное и нестабильное подключение, и тех, у кого интернет очень быстрый.

Мы понимали, что негативный опыт на старте просмотра может отразиться на всем впечатлении от платформы. Особенно, если речь о первом взаимодействии пользователя с продуктом. Поэтому для нас было важно быстрее решить проблему.

Та самая механика

В поисках оптимального решения мы разработали механизм, который замеряет скорость интернета, а потом, на основании этих данных, подбирает качество для старта воспроизведения. Например, если в конкретный момент пользовательская пропускная способность в диапазоне 6-8 Мб/сек и выше, мы можем предложить пользователю смотреть контент в качестве Full HD на старте воспроизведения.

Когда мы успеваем измерить скорость интернета? Мы делаем замеры везде, где запускается плеер. То есть проверяем пропускную способность сети на:

Потом мы учитываем данные о качестве подключения уже при показе основного контента. Например, когда вы выбираете контент и перед ним смотрите рекламу, плеер уже работает и в том числе замеряет пропускную способность сети. Данные о вашем подключении плеер хранит определенное время — мы называем его valid time. А потом с учетом собранных данных о подключении запускает контент соответствующего качества. Если ваше подключение будет меняться, плеер адаптирует качество контента.

Все видеобаннеры на старте, на главной странице, трейлеры и так далее — это ExoPlayer. Под капотом в них используется bandwidthMeter, который может передавать информацию о текущем битрейте. Ее мы и собираем.

Реализуется это так:

bandwidthMeter.addEventListener(Handler(Looper.getMainLooper())) { _, _, bitrateEstimate ->
    // получение текущего значения битрейта bitrateEstimate
    bandwidthManager.provideNewBitrate(bitrateEstimate)
}

Для сбора информации по текущей пропускной способности и ее хранения в кэше был создан менеджер (BandwidthManager). Его контракт:

interface BandwidthManager {

    /**
     * Предоставить новый доступный битрейт
     * @param bitrate новый битрейт
     */
    fun provideNewBitrate(bitrate: Long)

    /**
     * Текущее значения битрейта
     */
    val currentBandwidth: StateFlow<Long>
}

Как долго будет храниться значение, регулируется динамически с помощью Remote Configs. Если по истечении заданного времени мы не получаем новых данных о битрейте, то сбрасываем значение на дефолтное.

Теперь перейдем к использованию значения пропускной способности из менеджера. Нужно обеспечить старт на хорошем качестве в тех случаях, когда пользователь сидит на «хорошем интернете», то есть тип подключения не ниже 4G LTE или устройство подключено к Wi-Fi.

Для Android TV хорошее и стабильное подключение — через Ethernet-кабель. Специфика Android TV в том, что подключение по проводу или Wi-Fi не обеспечивает нам стабильную пропускную способность. Телевизор может находиться на даче, за пределами города, где плохо ловит интернет, есть перебои со связью. Поэтому старт воспроизведения контента с максимального качества в таком случае не будет правильным решением.

Если же речь о «хорошем интернете», нам следует обеспечить пользователю хорошую пропускную способность на старте. Делаем это через билдер BandwidthMeter:

override fun getCustomBandwidthMeter(
    context: Context,
    defaultInitialBitrate: Long?
): DefaultBandwidthMeter {
    val currentBitrate = bandwidthManager.currentBandwidth.value
    return DefaultBandwidthMeter.Builder(context)
        .setInitialBitrateEstimate(defaultInitialBitrate ?: DEFAULT_BITRATE)
        .setInitialBitrateEstimate(NETWORK_TYPE_4G, currentBitrate)
        .setInitialBitrateEstimate(NETWORK_TYPE_5G_SA, currentBitrate)
        .setInitialBitrateEstimate(NETWORK_TYPE_5G_NSA, currentBitrate)
        .setInitialBitrateEstimate(NETWORK_TYPE_WIFI, currentBitrate)
        .setInitialBitrateEstimate(NETWORK_TYPE_ETHERNET, currentBitrate)
        .build()
}

Фабрика по созданию BandwidthMeter может быть использована вместе с подключением слушателя битрейта:

override fun getBandwidthMeterWithListener(
    context: Context,
    bandwidthMeter: DefaultBandwidthMeter
): DefaultBandwidthMeter = bandwidthMeter.apply {
    addEventListener(Handler(Looper.getMainLooper())) { _, _, bitrateEstimate ->
        bandwidthManager.provideNewBitrate(bitrateEstimate)
    }
}

Для этого в качестве параметра bandwidthMeter можно передать из метода getCustomBandwidthMeter().

Еще стоит учитывать, что в случае Android TV и мобильной платформы время жизни актуального битрейта разное. Например, с мобильным устройством мы можем ехать в метро и постоянно ловить проблемы с интернетом, поэтому искомый параметр не должен быть актуальным долгое время. В случае же с Android TV мы говорим о более стабильной сети. К тому же экраны в Android TV выглядят иначе, чем в смартфоне, и мы не всегда можем попасть на загрузку какого-либо видеобаннера или трейлера перед тем, как начнет проигрываться контент. Поэтому значения времени жизни актуальной пропускной способности мы сделали разными для разных платформ. Пока это эксперимент, он в процессе.

Мы выяснили, что разное время жизни дало нам больше стартов с высокого качества на Android TV, чем если бы мы выбирали одинаковое время жизни информации о битрейте для обеих платформ.

Первые результаты

Всего за две недели с момента внедрения функции мы добились довольно впечатляющих результатов.

На Android Mobile мы на 0,33% улучшили конверсию в осознанный просмотр. Осознанным просмотром мы считаем любой просмотр контента дольше пяти секунд.

Кроме того, если посмотреть, с какого качества стартует контент на мобильных устройствах, то после внедрения функции просмотр контента стал на 171% чаще стартовать с самого высокого качества — Full HD 1080p. При этом доля сессий с плохим стартовым качеством уменьшилась на 50%.

Единственный показатель, который немного просел, это join time — время от нажатия кнопки «Смотреть» до показа первого кадра. Это вполне ожидаемо: из-за того, что мы подстраиваемся под текущий битрейт пользователя и улучшаем качество видео, банально увеличивается размер файла с контентом. Чем больше файл, тем дольше он скачивается и запускается, поэтому после релиза фичи на запуск контента мы стали тратить на 141 мс больше. Теперь это наша новая точка роста, и мы и уже работаем над функциями, которые позволят нам сократить время между нажатием кнопки «Смотреть» и показом первого кадра.

Что касается Android TV, доля сессий с максимальным стартовым качеством (Full HD 1080p) улучшилась еще значительнее — на 1594%. При этом долю сессий с плохим стартовым качеством мы уменьшили на 55%.

На Android TV время с момента нажатия кнопки «Смотреть» до старта воспроизведения тоже немного увеличилось — на 168 мс. Впрочем, как и с Android Mobile, мы планируем в ближайшее время нивелировать это увеличение запуском новой фичи.

Из-за технических особенностей функция пока доступна только на мобильных устройствах на базе Android и на Android TV. Но мы планируем разрабатывать и реализовывать подобную механику и на iOS.

На этом все. Спасибо, что читали! Если есть вопросы, обязательно пишите в комментариях. На все ответим!

Комментарии (3)


  1. saege5b
    09.07.2024 17:29
    +4

    Вот значит почему прилетают баннеры на 8К.


  1. Ribera-sun
    09.07.2024 17:29

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


  1. axelan
    09.07.2024 17:29

    Жаль, что только на андроиде и айфоне. На самсунг тв посмотрел версия 4.6.2 от марта последнее обновление, но не приуныл, так как чаще смотрю через веб-браузер.

    Кстати, не знаю помог ли мой предыдущий комментарий в этом блоге, но теперь в веб-версии Киона наконец-то можно менять полноэкранный режим просмотра двойным кликом мыши (раньше не было).
    В прошлый раз про недостаток веб-версии забыл сказать, что там почему-то нельзя управлять звуком клавишами вверх/вниз, а вот перемотка на несколько секунд (в зависимости от того сколько раз нажать) очень хорошо сделана клавишами влево/вправо. Осталось дождаться когда же будет регулироваться звук через клавиши вверх/вниз и Кион в веб-версии станет идеальным интернет-кинотеатром ;)