Русский
Русский
English
Статистика
Реклама

Стриминг

Перевод Стриминг видео с помощью Akka Streams

12.06.2021 18:20:44 | Автор: admin
Автор статьи, перевод которой мы сегодня публикуем, говорит, что стриминг видео не должен быть такой задачей, с которой у кого-либо возникают сложности. Всё дело в правильном подборе инструментов, среди которых можно отметить пакет Akka Streams. Использование этого пакета позволяет эффективно разрабатывать приложения для потоковой передачи видео.



Правда, не следует думать, что то, о чём мы будем тут говорить, подобно простому примеру, вроде println(Hello world), в котором используется система акторов Akka. Сегодня вы узнаете о том, как создать свой первый сервис для потоковой передачи видео (прошу прощения, если моё предположение неверно, и у вас это уже не первый такой проект). В частности, тут будут использованы пакеты Akka HTTP и Akka Streams, с помощью которых мы создадим REST API, который обладает способностями стриминга видеофайлов в формате MP4. При этом устроен этот API будет так, чтобы то, что он выдаёт, соответствовало бы ожиданиям HTML5-тега <video>. Кроме того, тут я скажу несколько слов о наборе инструментов Akka в целом, и о некоторых его компонентах, вроде Akka Streams. Это даст вам определённый объём теории, которая пригодится вам в работе. Но, прежде чем мы приступим к делу, хочу задать один вопрос.

Почему я решил рассказать о стриминге видео?


У того, что я посвятил эту статью потоковой передаче видео, есть три основных причины.

Первая причина заключается в том, что это, с моей точки зрения, захватывающая и сложная тема. Особенно если речь идёт о крупномасштабных стриминговых сервисах (вроде Netflix). Мне всегда хотелось получше разобраться в этой теме.

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

И третья причина, последняя в моём списке, но такая же важная, как и другие, кроется в том, что разработка стримингового сервиса это очень интересный способ знакомства с библиотекой Akka Streams, которая, на самом деле, значительно упрощает задачу создания подобного сервиса.

А теперь мы можем переходить к нашей основной теме.

Что такое набор инструментов Akka? Удобно ли им пользоваться?


Akka это опенсорсный набор инструментов, который нацелен на упрощение разработки многопоточных и распределённых приложений, и, кроме того, даёт программисту среду выполнения для подобных приложений. Системы, которые базируются на Akka, обычно очень и очень хорошо масштабируются. Проект Akka основан на модели акторов, в нём используется система конкурентного выполнения кода, основанная на акторах. Создатели этого проекта многое почерпнули из Erlang. Инструменты Akka написаны на Scala, но в проекте имеются DSL и для Scala, и для Java.

Если говорить об удобстве работы с Akka, то, полагаю, писать код с использованием этого набора инструментов весьма удобно. Если вы хотите получше его изучить рекомендую начать с этого материала.

Основной объём кода, который мы будем тут рассматривать, будет использовать пакеты HTTP и Streams. Мы практически не будем пользоваться стандартным пакетом Akka Actors.

Теперь, когда мы разобрались с самыми базовыми сведениями об Akka, пришло время вплотную заняться пакетом Akka Streams.

Что такое Akka Streams?


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

Для нас важен тот факт, что в Akka Streams есть встроенный механизм back-pressure (обратное давление). Благодаря этому решается одна из самых сложных проблем мира стриминговой передачи данных. Это настройка правильной реакции поставщика данных на работу в условиях, когда потребитель данных не может справиться с нагрузкой. И эту проблему решает инструмент, которым мы будем пользоваться, а нам остаётся лишь научиться работать с этим инструментом, не вдаваясь в какие-то чрезмерно сложные и запутанные темы.

Пакет Akka Streams, кроме того, даёт в наше распоряжение API, который совместим с интерфейсами, необходимыми для работы с Reactive Streams SPI. И, между прочим, стоит отметить, что сам проект Akka входит в число основателей инициативы Reactive Streams.

Про Akka Streams мы поговорили. Поэтому можем переходить к нашей следующей теоретической теме.

Что такое Akka HTTP?


Akka HTTP это, как и Akka Streams, пакет, входящий в набор инструментов Akka. Этот пакет основан на пакетах Akka Streams и Akka Actors. Он направлен на то, чтобы упростить работу приложений, в которых используются инструменты Akka, с внешним миром по протоколу HTTP. Этот пакет поддерживает и серверные, и клиентские возможности. Поэтому с его помощью можно создавать и REST API, и HTTP-клиентов, которые отправляют запросы к неким внешним сервисам.

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

HTML5-тег <video>


Тег <video> это новый элемент, который появился в HTML5. Он создавался как замена Adobe Video Player. Несложно понять, что главная задача этого HTML-элемента заключается в предоставлении разработчикам возможностей встраивания в HTML-документы медиаплееров, способных воспроизводить видеофайлы. Собственно, этот тег очень похож на <img>.

В теге <video> размещают тег <source>, имеющий два важных атрибута. Первый это src, который используется для хранения ссылки на видео, которое нужно воспроизвести. Второй это type, который содержит сведения о формате видео.

Между открывающим и закрывающим тегом <video> </video> можно ввести какой-то текст, который будет использован в роли текста, выводимого вместо элемента <video> в тех случаях, когда этот элемент не поддерживается браузером. Но в наши дни тег <video> поддерживает даже Internet Explorer, поэтому вероятность возникновения ситуации, в которой может понадобиться подобный текст, стремится к нулю.

Как будет работать стриминг с использованием тега и FileIO?</font></h2>Хотя на первый взгляд кажется, что стриминг с использованием тега <video> и FileIO это нечто архисложное, если в этот вопрос немного вникнуть, окажется, что ничего особенного в нём нет. Дело в том, что то, о чём идёт речь, представлено готовыми блоками, из которых нужно лишь собрать то, что нам нужно.На стороне сервера основная нагрузка ложится на объект <code>FileIO</code>. Он будет генерировать события, содержащие фрагменты файла, потоковую передачу которого мы осуществляем. Конечно, размеры этих фрагментов поддаются настройке. И, более того, настроить можно и позицию, начиная с которой будет осуществляться стриминг файла. То есть видео необязательно смотреть сначала его можно начинать смотреть с любого места, интересующего пользователя. Всё это отлично сочетается с возможностями тега <code><video></code>, выполняющего запрос HTTP GET с заголовком <code>Range</code> для того чтобы включить воспроизведение видео без его предварительной загрузки.Вот пара примеров запросов, выполняемых элементом <code><video></code>:<img src="http://personeltest.ru/aways/lh3.googleusercontent.com/Dfgd_RjgpV9W3jzBF9TVNLT_n8cAf5_VfvhxbfeK5wYH5slwUtXhjQ0FlZ0I79gCWsNgIF1Q3q7nPty5HqpCpgXIYrEtjQINuyMaMHe1nWu228-p8o9Hf3n-cHNZN_5iS0QGktk" align="center"><img src="http://personeltest.ru/aways/lh3.googleusercontent.com/SQPBs8xy8HVsT8cw2_WRoOnQW1dqKRp2WVSAzfFsbCBkSmETbm7NKS8zMLBdwcWdIo1AQDO_tSJJw1_2Tcd_oMoaBzdTwDz62Tq2jtzKX0ujmuCEqo99NKH_YLnlL6FQbZ5UOd0" align="center">Если кому интересно заголовок <code>Range:bytes=x-</code> отвечает за выбор позиции, с которой начинается воспроизведение видео. Первый запрос уходит на сервер в начале воспроизведения видео, а второй может быть отправлен тогда, когда пользователь решит куда-нибудь перемотать видео.Сейчас, после довольно-таки длинного вступления, пришло время заняться кодом.<h2><font color="#3AC1EF">Пишем стриминговый сервис</font></h2>В нескольких следующих разделах я расскажу о реализации серверной части нашего стримингового сервиса. А потом мы создадим простую HTML-страницу, с помощью которой проверим правильность работы этого сервиса.Я люблю делать предположения, поэтому сделаю ещё одно, которое заключается в том, что я ожидают, что тот, кто это читает, владеет основами Scala и SBT.<h3><font color="#3AC1EF">1</font></h3>Добавим в файл <code>build.sbt</code> необходимые зависимости. В этом проекте нам понадобится 3 пакета: <code>akka-http</code>, <code>akka-actor-typed</code> (пакета <code>akka-actor</code>, в теории, достаточно, но никогда нельзя забывать о типобезопасности) и <code>akka-stream</code>.<source lang="scala">libraryDependencies ++= Seq("com.typesafe.akka" %% "akka-actor-typed" % "2.6.14","com.typesafe.akka" %% "akka-stream" % "2.6.14","com.typesafe.akka" %% "akka-http" % "10.2.4")</source><h3><font color="#3AC1EF">2</font></h3>Теперь можно создать главный класс, ответственный за запуск приложения. Я решил расширить класс <code>App</code>. Мне кажется, что это удобнее, чем создавать метод <code>main</code>. На следующем шаге мы поместим сюда код, имеющий отношение к созданию системы акторов и HTTP-сервера.<source lang="scala">object Runner extends App {}</source><h3><font color="#3AC1EF">3</font></h3>После создания главного класса мы можем добавить в него код, о котором говорили выше.<source lang="scala">object Runner extends App {val (host, port) = ("localhost", 8090)implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "akka-video-stream")Http().newServerAt(host, port)}</source>Сейчас нас вполне устроит такая конфигурация. На последнем шаге мы добавим в код вызов метода <code>bind</code>, что позволит открыть доступ к нашему REST API. Тут мы создаём объект <code>ActorSystem</code> с именем <code>akka-video-stream</code> и HTTP-сервер, прослушивающий порт <code>8090</code> на локальном компьютере. Не забудьте о ключевом слове <code>implicit</code> в определении системы акторов, так как подобный неявный параметр необходим в сигнатуре метода <code>Http</code>.<h3><font color="#3AC1EF">4</font></h3>А тут мы, наконец, реализуем конечную точку REST API, используемую для обработки запросов от тега <code><video></code>.<source lang="scala">object Streamer {val route: Route =path("api" / "files" / "default") {get {optionalHeaderValueByName("Range") {case None =>complete(StatusCodes.RangeNotSatisfiable)case Some(range) => complete(HttpResponse(StatusCodes.OK))}}}}</source>Как видите, я создал конечную точку с URL <code>api/files/default/</code>. В её коде проверяется, есть ли в запросе заголовок <code>Range</code>. Если он содержит корректные данные сервер возвращает ответ с кодом <code>200</code> (<code>OK</code>). В противном случае возвращается ответ с кодом <code>416</code> (<code>Range Not Satisfiable</code>).<h3><font color="#3AC1EF">5</font></h3>Пятый шаг нашей работы отлично подходит для реализации метода, ради которого, собственно, и была написана эта статья.<source lang="scala">private def stream(rangeHeader: String): HttpResponse = {val path = "path/to/file"val file = new File(path)val fileSize = file.length()val range = rangeHeader.split("=")(1).split("-")val start = range(0).toIntval end = fileSize - 1val headers = List(RawHeader("Content-Range", s"bytes ${start}-${end}/${fileSize}"),RawHeader("Accept-Ranges", s"bytes"))val fileSource: Source[ByteString, Future[IOResult]] = FileIO.fromPath(file.toPath, 1024, start)val responseEntity = HttpEntity(MediaTypes.`video/mp4`, fileSource)HttpResponse(StatusCodes.PartialContent, headers, responseEntity)}</source>Тут я сделал следующее:<ul><li>Загрузил файл, потоковую передачу которого я хочу организовать, а затем, учитывая заголовок из запроса, и данные о файле, нашёл позицию в файле, с которой начнётся стриминг, а так же сформировал заголовок <code>Content Range</code>.</li><li>С помощью <code>FileIO</code> создал поток из ранее загруженного файла. Затем я использовал этот поток в роли данных в <code>HttpEntity</code>.</li><li>Я создал ответ, <code>HttpResponse</code>, с кодом <code>206</code> (<code>Partial Content</code>), с соответствующими заголовками и с телом в виде <code>responseEntity</code>.</li></ul>Ещё мне хочется подробнее поговорить о <code>FileIO</code>, так как это самый удивительный механизм во всей статье. Что, на самом деле, происходит при выполнении строки <code>FileIO.fromPath(file.toPath, 1024, start)</code>?Тут, из содержимого файла, находящегося по заданному пути, создаётся объект <code>Source</code> (Akka-аналог Producer из Reactive Streams). Каждый элемент, выдаваемый этим объектом, имеет размер, в точности равный 1 Мб. Первый элемент будет взят из позиции, указанной в параметре <code>start</code>. Поэтому, если в <code>start </code>будет 0 первый элемент окажется первым мегабайтом файла.<h3><font color="#3AC1EF">6</font></h3>Мы уже реализовали основную логику серверной части приложения. А сейчас нам надо отрефакторить её код для того чтобы нашим сервером можно было бы пользоваться.Начнём с внесения изменений в определение REST API:<source>complete(HttpResponse(StatusCodes.Ok)) => complete(stream(range))</source>Получается, что вместо того, чтобы просто возвращать <code>OK</code>, мы вызываем метод <code>stream</code> с передачей ему параметра <code>range</code> и начинаем стриминг.Нельзя забывать о том, что наш API всё ещё недоступен для внешнего мира. Поэтому нам нужно модифицировать соответствующий фрагмент кода, ответственный за запуск HTTP-сервера:<source>Http().newServerAt(host, port) =>Http().newServerAt(host, port).bind(Streamer.route)</source>Готово! Теперь у нас есть рабочий бэкенд, а наш REST API ждёт подключений от любых программ, которым он нужен. Осталось лишь всё протестировать.<h2><font color="#3AC1EF">Тестирование стримингового сервиса</font></h2>Мы, чтобы протестировать приложение, создадим простую HTTP-страницу, единственным достойным внимания элементом которой будет тег <code><video></code>. Причём, обо всём, что надо знать для понимания работы этой страницы, мы уже говорили. Поэтому я просто приведу ниже полный код соответствующего HTML-документа.То, что вы в итоге увидите в окне браузера, открыв эту страницу, должно, более или менее, напоминать то, что я покажу ниже. Конечно, ваш стриминговый сервис вполне может передавать не тот видеофайл, который использовал я.<source lang="html"><!DOCTYPE html><html lang="en"><head><title>Akka streaming example</title></head><body style="background: black"><div style="display: flex; justify-content: center"><video width="1280" height="960" muted autoplay controls><source src="http://personeltest.ru/away/localhost:8090/api/files/default" type="video/mp4">Update your browser to one from XXI century




Тут мне хотелось бы обратить ваше внимание на 5 важных вещей:

  1. Я использовал возможности тега <source> вместо использования соответствующих атрибутов тега <video>.
  2. В атрибуте src тега <source> я указал путь, при обращении к которому бэкенд начнёт потоковую передачу видеофайла.
  3. В атрибуте type тега <source> я указал тип файла.
  4. Я добавил к тегу <video> атрибуты autoplay и muted для того чтобы видео начинало бы воспроизводиться автоматически.
  5. К тегу <video> я добавил и атрибут controls, благодаря чему будут выводиться элементы управления видеоплеера, встроенного в страницу.

На элемент <div> можете особого внимания не обращать. Он тут нужен лишь для стилизации плеера.

Для проверки правильности работы системы достаточно запустить бэкенд и открыть вышеописанный HTML-документ в любом современном браузере.


Правильная работа стримингового сервиса

Обратите внимание на то, что автоматическое воспроизведение видео не начнётся до тех пор, пока к тегу <video> не будут добавлены атрибуты muted и autoplay. Если не оснастить тег <video> этими атрибутами воспроизведение придётся включать вручную, нажимая на соответствующую кнопку.

Как и в любом обычном программном проекте, мы, после создания и тестирования первого варианта программы, можем переосмыслить решения, принятые в самом начале, и подумать о том, как улучшить её код.

Что можно улучшить?


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

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

Итоги


Сегодня я постарался доказать то, что реализация простого стримингового сервиса это, при условии использования правильных инструментов, проще, чем кажется. Использование инструментов Akka и подходящего HTML-тега способно значительно сократить объём работы. Правда, не забывайте о том, что тут показан очень простой пример. Для реализации реального стримингового сервиса этого может быть недостаточно.

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

Вот GitHub-репозиторий с кодом проекта.

Какие инструменты вы выбрали бы для создания собственного стримингового сервиса?


Подробнее..

Разработать видеоплатформу за 90 дней

27.08.2020 16:05:58 | Автор: admin

Этой весной мы оказались в очень весёлых условиях. Из-за пандемии стало ясно, что наши летние конференции необходимо переносить в онлайн. А чтобы провести их в онлайне качественно, нам не подходили готовые софтовые решения, требовалось написать собственное. И на это у нас было три месяца.


Понятно, что это были увлекательные три месяца. Но со стороны не вполне очевидно: что вообще представляет собой платформа для онлайн-конференций? Из каких частей она состоит? Поэтому на последней из летних конференций DevOops я расспросил тех, кто отвечал за эту задачу:


  • Николай Молчанов технический директор JUG Ru Group;
  • Владимир Красильщик прагматичный Java-программист, занимающийся бэкендом (вы также могли видеть его доклады на наших Java-конференциях);
  • Артём Никонов отвечает за весь наш видеостриминг.

Кстати, на осенне-зимних конференциях мы будем использовать улучшенную версию той же платформы так что многие хабрачитатели ещё окажутся её пользователями.



Общая картина


Каким был состав команды?


Николай Молчанов: У нас есть аналитик, дизайнер, тестировщик, три фронтендера, бэкендер. И, конечно, T-shaped специалист!


Как в целом выглядел процесс?


Николай: До середины марта у нас к онлайну не было готово вообще ничего. А 15 марта завертелась вся карусель с онлайном. Мы завели несколько репозиториев, спланировали, обсудили базовую архитектуру и сделали всё за три месяца.


Это, конечно, прошло классические этапы планирования, архитектуры, выбора фич, голосование за эти фичи, политики этих фич, их дизайна, разработки, тестирования. В итоге 6 июня мы выкатили всё в прод на TechTrain. На всё про всё было 90 дней.


Получилось ли успеть то, на что мы коммитились?


Николай: Раз мы сейчас участвуем в конференции DevOops в онлайне значит, получилось. Я лично закоммитился на главную вещь: принесу заказчикам инструмент, при помощи которого можно будет сделать конференцию в онлайне.


Задача стояла так: дайте нам инструмент, с помощью которого мы сможем транслировать наши конференции обладателям билетов.


Все планирование было разбито на несколько этапов, и все фичи (около 30 глобальных), были поделены на 4 категории:


  • которые мы сделаем обязательно (без них жить не можем),
  • которые мы сделаем во вторую очередь,
  • которые мы никогда не сделаем,
  • и которые никогда-никогда не сделаем.

Все фичи из первых двух категорий мы сделали.


Я знаю, что всего было заведено 600 JIRA-задач. За три месяца вы сделали 13 микросервисов, и подозреваю, что они написаны не только на Java. Вы использовали разные технологии, у вас поднято два Kubernetes-кластера в трех зонах доступности и 5 RTMP-стримов в Amazon.


Давайте теперь разберёмся с каждой составляющей системы по отдельности.


Стриминг


Начнём с того, когда у нас уже есть видео-картинка, и она передаётся на какие-то сервисы. Артём, расскажи, как происходит этот стриминг?


Артём Никонов: Общая схема у нас выглядит так: изображение с камеры -> наша пультовая -> локальный RTMP-сервер -> Amazon -> видеоплеер. Подробнее писали об этом на Хабре в июне.


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


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


Сигналы от этих устройств попадают в компьютеры с платами захвата, ввода/вывода, звуковыми карточками. Там сигналы микшируются, собираются в лейауты:



Пример лейаута на 4-х спикеров



Пример лейаута на 4-х спикеров


Дальше беспрерывный эфир обеспечивается с помощью трёх компьютеров: есть одна главная машина и пара работающих по очереди. Первый компьютер собирает первый доклад, второй перерыв, первый следующий доклад, вторый следующий перерыв и так далее. А главная машина микширует первую со второй.


Таким образом получается некий треугольник, и в случае падения любого из этих узлов мы можем быстро и без потери качества продолжить доставлять клиентам контент. Такая ситуация у нас была. На первой неделе конференций мы чинили одну машину, включали/выключали. Кажется, что люди довольны нашей отказоустойчивостью.


Далее потоки из компьютеров попадают на локальный сервер, у которого две задачи: роутить RTMP-потоки и записывать бэкап. Таким образом, у нас есть несколько точек записи. Затем потоки видео отправляются в часть нашей системы, построенную на амазоновских SaaS-сервисах. Используем MediaLive, S3, CloudFront.


Николай: А что там происходит до того, как видео попадёт к зрителям? Вы же должны его нарезать как-то?


Артём: Мы сжимаем со своей стороны видео, отправляем его в MediaLive. Там запускаем транскодеры. Они перекодируют видео в режиме реального времени в несколько разрешений для того, чтобы люди могли смотреть их на телефонах, через плохой интернет на даче и так далее. Потом эти стримы режутся на чанки, так работает протокол HLS. На фронтенд мы отдаем плейлист, в котором есть указатели на эти чанки.


Мы используем разрешение 1080р?


Артём: По ширине у нас как 1080p видео 1920 пикселей, а по высоте чуть меньше, картинка более вытянутая на это есть свои причины.


Плеер


Артём описал, как видео попадает в стримы, как распределяется на разные плейлисты для разных разрешений экранов, режется на чанки и попадает в плеер. Коля, расскажи теперь, что это за плеер, как он потребляет стрим, почему HLS?


Николай: У нас есть плеер, который наблюдают все зрители конференции.



По сути, это обёртка над библиотекой hls.js, на которой написано много других плееров. Но нам была необходима очень специфическая функциональность: перемотка назад и отметка на месте, в котором находится человек, какой доклад он сейчас смотрит. Также нужны были собственные лейауты, всякие логотипы и все прочее, что встроилось у нас. Поэтому мы решили написать собственную библиотеку (обёртку над HLS) и встроить это на сайт.


Это корневая функциональность, так что её реализовали практически первой. А потом вокруг этого всё уже обрастало.


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



Пример таймлайна


Прямо в плеер встроена кнопка для выведения таймлайна всех докладов


Николай: Да, мы сразу решали проблему навигации пользователя. В середине апреля решили, что не будем транслировать каждую из наших конференций на отдельном сайте, а объединим все на одном. Чтобы пользователи билетов Full Pass могли свободно переключаться между разными конференциями: и прямым эфиром, и записями прошедших.


А чтобы пользователям было проще передвигаться по текущему стриму и переключаться между треками, решили сделать кнопку Весь эфир и горизонтальные карточки докладов для переключения между треками и докладами. Там есть управление с клавиатуры.


Были какие-то технические сложности с этим?


Николай: Были с полоской прокрутки, на которой отмечаются точки начала разных докладов.


В итоге вы реализовали эти отметки на полосе прокрутки раньше, чем похожее сделал YouTube?


Артём: У них это тогда было в бете. Кажется, что это довольно сложная фича, потому что они частично тестировали ее на пользователях в течение последнего года. И вот теперь она дошла до прода.


Николай: Но мы действительно до прода донесли быстрее. Честно сказать, что за этой простой фичей стоит огромное количество и бэкенда, и фронтенда, и расчетов и матана внутри плеера.


Фронтенд


Давайте разберемся, как этот контент, который мы показываем (карточку доклада, спикеры, сайт, расписание), выходит на фронтенд?


Владимир Красильщик: У нас есть несколько внутренних айтишных систем. Есть система, в которой заведены все доклады и все спикеры. Есть процесс, по которому докладчик принимает участие в конференции. Спикер подает заявку, система её захватывает, дальше есть некий пайплайн, по которому создаётся доклад.



Так спикер видит пайплайн


Эта система наша внутренняя разработка.


Дальше из отдельных докладов нужно построить расписание. Как известно, это NP-сложная задача, но мы её как-то решаем. Для этого запускаем другой компонент, который формирует расписание и засовывает его в сторонний облачный сервис Contentful. Там всё выглядит уже как таблица, в которой есть дни конференции, в днях временные слоты, а в слотах доклады, перерывы или спонсорские активности. Так что контент, который мы видим, располагается в стороннем сервисе. И стоит задача донести его до сайта.


Казалось бы, сайт это просто страница с плеером, и ничего сложного тут нет. За исключением того, что это не так. Бэкенд, стоящий за этой страницей, идёт в Contentful, достает оттуда расписание, формирует некоторые объекты и отсылает на фронтенд. При помощи вебсокет-соединения, которое делает каждый клиент нашей платформы, мы с бэкенда на фронтенд закидываем ему обновление в расписании.


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


Николай: Здесь важно уточнить, что наш сайт не является классическим SPA-приложением. Это и свёрстанный, отрендеренный сайт, и SPA. На самом деле Google видит этот сайт как отрендеренный HTML. Это хорошо для SEO и для доставки пользователю контента. Он не ждет загрузки 1,5 мегабайт JavaScript, чтобы потом увидеть страницу, он сразу видит уже отрендеренную страницу, а вы это чувствуете каждый раз, когда переключаете доклад. Всё получается за полсекунды, так как контент уже готов и выложен в правильное место.


Подведём черту под всем вышесказанным, перечислив технологии. Тёма рассказал, что у нас есть 5 Amazon-стримов, туда доставляем видео и звук. Там у нас bash-скрипты, с их помощью запускаем, конфигурим


Артём: Это происходит через API AWS, там есть еще много побочных технических сервисов. Мы разделили свои обязанности так, что я доставляю на CloudFront, а фронтенд- и бэкенд-разработчики оттуда забирают. У нас некоторое количество своих обвязок для упрощения выкладки контента, который мы делаем потом в 4К и т.д. Поскольку сроки были очень сжатые, мы практически целиком сделали это на базе AWS.


Дальше все это попадает в плеер, используя бэкенд системы. У нас в плеере TypeScript, React, Next.JS. И на бэкенде у нас есть несколько сервисов на С#, Java, Spring Boot и Node.js. Это все разворачивается с помощью Kubernetes, используя инфраструктуру Яндекс.Облака.


Ещё хочу заметить, что когда мне понадобилось познакомиться с платформой, это оказалось несложно: все репозитории находятся на GitLab, всё хорошо названо, написаны тесты, есть документация. То есть даже в авральном режиме заботились о таких вещах.


Бизнес-ограничения и аналитика


Мы таргетировались по бизнес-требованиям на 10 000 пользователей. Самое время рассказать про бизнес-ограничения, которые у нас были. Мы должны были обеспечивать высокую нагрузку, обеспечивать выполнение закона о сохранении персональных данных. А что ещё?


Николай: Изначально мы отталкивались от требований к видео. Самое главное распределённое хранение видео по миру для быстрой доставки клиенту. Из других разрешение 1080р, а также перемотка назад, что у многих других в лайв-режиме не реализовано. Позже мы добавили возможность включить скорость 2x, с её помощью можно догнать лайв и дальше смотреть конференцию в реальном времени. И ещё по ходу появилась функциональность разметки таймлайна. Плюс к этому мы должны были быть отказоустойчивыми и выдерживать нагрузку 10 000 соединений. С точки зрения бэкенда это примерно 10 000 соединений умножить на 8 запросов на каждый рефреш страницы. А это уже 80 000 RPS/сек. Довольно много.


Ещё были требования к виртуальной выставке с онлайн-стендами партнёров?


Николай: Да, это нужно было сделать довольно быстро и универсально. У нас было до 10 компаний-партнёров на каждую конференцию, и страницы их всех нужно было заверстать за неделю-две. При этом контент у них немного различается по формату. Но был сделан определённый шаблонизатор, собирающий эти страницы на лету, практически без дальнейшего участия по разработке.


Было еще требования по аналитике просмотров в реал-тайме и статистике. Знаю, что мы используем для этого Prometheus, а расскажите подробнее: какие требования мы выполняем по аналитике, и как это реализуется?


Николай: Изначально у нас есть маркетологические требования по сбору для А/В-тестирования и по сбору информации для того, чтобы понять, как правильно клиенту доставлять лучший контент в дальнейшем. Еще есть требования по некой аналитике по партнерским активностям и аналитика, которую вы видите (счетчик посещений). Вся информация собирается в реал-тайме.


Эту информацию мы можем выдавать в агрегированном виде даже спикерам: сколько людей тебя смотрели в определенный момент времени. При этом для соблюдения 152 ФЗ личный кабинет и персональные данные не трекаются никак.


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


Фрод


У нас есть механизмы антифрода?


Николай: В связи с жёсткими временными рамками с точки зрения бизнеса изначально не ставилась задача сразу же блокировать лишние соединения. Если два пользователя заходили под одним и тем же аккаунтом, они могли посмотреть контент. Но мы знаем, сколько одновременных просмотров было с одного аккаунта. И нескольких особо злостных нарушителей мы забанили.


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


Чтобы это все происходило, вы должны полностью трассировать всех пользователей от входа до выхода, всегда знать что они делают. Как устроена эта система?


Владимир: Я бы хотел рассказать про аналитику и статистику, которую мы потом анализируем для успешности доклада или можем предоставить потом партнерам. Все клиенты присоединены по вебсокет-соединению к определенному кластеру бэкенда. Там стоит Hazelcast. Каждый клиент в каждый период времени отсылает, что он делает и какой трек он смотрит. Дальше эта информация быстрыми Hazelcast-джобами агрегируется и отсылается в обратку всем, кто смотрит эти треки. Мы видим в углу, сколько людей сейчас находятся вместе с нами.



Эта же информация складируется в Mongo и уезжает в наше озеро данных, по которому мы имеем возможность строить более интересный график. Приходит вопрос: сколько уникальных пользователей посмотрели данный доклад? Мы идем в Postgres, там пинги всех людей, которые пришли по id этого доклада. Собрали, агрегировали уникальных, и теперь можем понять.


Николай: Но при этом мы получаем ещё реалтайм-данные с Prometheus. Он натравлен на все Kubernetes-сервисы, на сам Kubernetes. Собирает абсолютно всё, и с Grafana мы можем строить любые графики в реальном времени.


Владимир: С одной стороны, мы это сгружаем для дальнейшей обработки типа OLAP. А для OLTP приложение сгружает все это дело в Prometheus, Grafana и графики даже сходятся!


Тот самый случай, когда графики сходятся.


Динамические изменения


Расскажите, как выкатываются динамические изменения: если доклад отменился за 6 минут до начала, какая цепочка действий? Какой пайплайн срабатывает?


Владимир: Пайплайн очень условный. Есть несколько возможностей. Первая программа формирования расписания сработала и изменила это расписание. Изменённое расписание выгружается в Contentful. После чего бэкенд понимает, что есть изменения по данной конференции в Contentful, берёт и пересобирает. Всё собирается и отсылается по websocket.


Вторая возможность, когда всё происходит в бешеном темпе: редактор руками меняет в Contentful информацию (ссылку на Telegram, презентацию докладчика и т.д.) и срабатывает та же самая логика, что и в первый раз.


Николай: Все происходит без рефреша страницы. Все изменения происходят абсолютно бесшовно для клиента. Также и с переключением докладов. Когда подходит время, меняется доклад и интерфейс.


Владимир: Также и временные отсечки начала докладов в таймлайне. В самом начале ничего нет. А если навести мышку на красную полоску, то в какой-то момент, благодаря режиссеру трансляции, появятся отсечки. Режиссер ставит правильное начало трансляции, бэкенд это изменение схватывает, рассчитывает соответственно расписанию конференции время начала и окончания докладов всего трека, отправляет нашим клиентам, плеер рисует отсечки. Теперь пользователь может спокойно навигироваться в начало и конец доклада. Это было жесткое бизнес-требование, очень удобное и полезное. Ты не тратишь время, чтобы найти настоящее время начала доклада. А когда мы сделаем превью, будет вообще замечательно.


Деплоймент


Я бы хотел спросить про деплоймент. Коля и команда в начале убили много времени, чтобы настроить всю инфраструктуру, в которой у нас всё разворачивается. Расскажи, из чего это всё?


Николай: У нас изначально было требование с технической точки зрения к продукту максимально абстрагироваться от какого-либо вендора. Прийти в AWS делать Terraform-скрипты конкретно AWS-овские, или конкретно яндексовские, или Azure-овские и т.д. не очень подходило. Мы должны были в своё время куда-то съехать.


Первые недели три мы постоянно искали путь, как это лучше сделать. В итоге пришли к тому, что Kubernetes в данном случае это наше всё, потому что позволяет делать автоматически-масштабируемые сервисы, автовыкатку и получить из коробки практически все сервисы. Естественно, надо было обучить все сервисы работе с Kubernetes, Docker, и команде тоже научиться.


У нас два кластера. Тестовый и продовский. Они абсолютно одинаковые с точки зрения железа, настроек. Имплементируем инфраструктуру как код. Все сервисы автоматическим пайплайном раскатываются в три среды из фичи-веток, из мастер-веток, из тестовых, из GitLab. Это максимально интегрировано в GitLab, максимально интегрировано с Elastic, Prometheus.


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


Про тесты


Вы почти всё тестируете, тяжело поверить, как вы всё написали. Можете рассказать как по бэкенду по тестам: насколько все покрыто, какие тесты?


Владимир: Написано два типа тестов. Первые компонентные тесты. Тесты уровня подъема всего спрингового приложения и базы в Testcontainers. Это проверка самых высокоуровневых бизнес-сценариев. Я не тестирую функции. Мы тестируем только какие-то крупные штуки. Например, прямо в тесте эмулируется процесс логина пользователя, запрос этим пользователем билетов, куда он может сходить, запрос доступа на просмотр стрима. Очень понятные пользовательские сценарии.


Примерно то же самое реализовано в так называемых интеграционных тестах, которые реально бегут на среде. Фактически, когда очередной деплоймент в прод раскатывается, на проде также бегут настоящие базовые сценарии. Тот же самый логин, запрос билетов, запрос доступа до CloudFront, проверка того, что стрим действительно цепляется с моими разрешениями, проверка режиссерского интерфейса.


На данный момент у меня на борту примерно 70 компонентных тестов и около 40 интеграционных. Покрытие очень близко к 95%. Это по компонентным, по интеграционным поменьше, там столько просто не надо. Учитывая то, что в проекте всякие кодогенерации, это очень хороший показатель. Никакого другого способа сделать то, что мы сделали за три месяца, не было. Потому что если бы мы тестировали ручным образом, отдавая фичи нашей тестировщице, а она бы находила баги и возвращала нам на фиксы, то этот round trip по отлаживанию кода был бы очень долгий, и мы бы не влезли ни в какие сроки.


Николай: Условно, чтобы провести регресс на всей платформе при изменении какой-то функции, нужно два дня сидеть и тыкать везде.


Владимир: Поэтому большой успех, что, когда я эстимирую фичу, говорю, что мне нужно 4 дня на две простые ручки и 1 websocket, Коля разрешает. Он уже привык, что в эти 4 дня заложены 2 типа тестов, и потом, скорее всего, это будет работать.


Николай: У меня тоже написано 140 тестов: компонентных + функциональных, которые делают то же самое. Все те же самые сценарии тестируются и на продакшене, на тесте и на деве. Также недавно у нас появились функциональные базовые UI-ные тесты. Так мы покрываем самые базовые функциональности, которые могут развалиться.


Владимир: Конечно же, стоит рассказать про нагрузочные тесты. Нужно было проверить платформу под нагрузкой, приближенной к реальной, чтобы понять, как оно все, что происходит с Rabbit, что происходит с JVM-ками, сколько реально надо памяти.


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


Артём: Тестили итеративно. Организовывая митапы. В процессе организации митапов было примерно 2300 JIRA-тикетов. Это просто шаблонные вещи, которые люди делали, чтобы сделать митапы. Мы брали части платформы на отдельную страницу для митапов, которой занимался Кирилл Толкачев (tolkkv).


Честно говоря, больших проблем не было. Буквально пару раз ловили баги по кэшированию на CloudFront, решили довольно быстро просто перенастроили политики. Багов было значительно больше в людях, в системах стриминга на площадке.


Во время конференций пришлось писать еще несколько экспортёров для того чтобы покрыть больше оборудования и сервисов. Местами приходилось делать свои велосипеды только ради метрик. Мир AV (аудио-видео) железа не очень радужный у тебя есть какое-то API оборудования, на которое ты просто не можешь повлиять. И далеко не факт, что получится забрать ту информацию, которая тебе нужна. Вендоры железа реально медленные, и от них почти невозможно добиться желаемого. Итого более 100 железок, отдают они не то, что нужно, а ты пишешь странные и избыточные экспортёры, благодаря которым можно хоть как-то дебажить систему.


Оборудование


Я помню, как до начала конференций мы частично дозакупали оборудование.


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


С интернетом у нас похожая история. В офисе, где находятся наши студии, мы между этажами протащили лютую сеть.


Артём: У нас 20 ГБит оптики между этажами. Дальше по этажам где-то оптика, где-то нет, но все-таки меньше, чем гигабитных, каналов нет мы гоняем по ним между треками конференции видео. Вообще очень удобно работать на своей инфраструктуре, на офлайн-конференциях на площадках так редко получается делать.


Еще не работая в JUG Ru Group, я видел, как за ночь разворачиваются аппаратные на офлайн-конференциях, где стоит большой монитор со всеми метриками, которые вы строите в Grafana. Сейчас также есть помещение-штаб, в котором сидит команда разработки, которая во время конференции чинит какие-то баги и разрабатывает фичи. При этом есть система мониторинга, которая выводится на большой экран. Артём, Коля и другие ребята сидят и смотрят, чтобы это все не падало и красиво работало.


Курьёзы и проблемы


Вы хорошо рассказали о том, что у нас есть стриминг с Амазоном, есть плеер с вебом, все написано на разных языках программирования, обеспечивается отказоустойчивость и другие бизнес-требования, в том числе есть личный кабинет, который поддерживается для юридических и физических лиц, и мы можем интегрироваться с кем-то по OAuth 2.0, есть антифрод, блокировка пользователя. Мы можем динамически выкатывать изменения, потому что сделали это хорошо, и при этом это все тестируется.


Мне интересно узнать, какие были курьёзы с тем, чтобы что-то запустилось. Были ли странные ситуации, когда вы разрабатывали бэкенд, фронтенд, получалась какая-то дичь и вы не понимали, что с этим делать?


Владимир: Мне кажется, такое было только последние три месяца. Каждый день. Как вы можете увидеть, все мои волосы вырваны.



Владимир Красильщик после 3 месяцев, когда получалась какая-то дичь и никто не понимал, что с этим делать


Каждый день что-то такое было, когда был такой момент, когда ты берешь и рвёшь на себе волосы, либо понимаешь, что больше никого нет, и только ты можешь это сделать. Первым большим мероприятием у нас был TechTrain. 6 июня в 2 часа ночи у нас еще не было раскатано продакшен-окружение, его раскатывал Коля. И не работал личный кабинет, как сервер авторизации по OAuth2.0. Мы превратили его в провайдера OAuth2.0, чтобы к нему подключить платформу. Я работал, наверное, уже 18 час подряд, смотрел в компьютер и ничего не видел, не понимал, почему он не работает, и удалённо Коля смотрел в мой код, искал баг в конфигурации Spring, нашел, и ЛК заработал, и в продакшене тоже.


Николай: И за час до TechTrain релиз состоялся.


Здесь сложились очень многие звёзды. Нам крайне повезло, потому что у нас сложилась просто супер-команда, и все задрайвились идеей сделать онлайн. Все эти три месяца нас драйвило то, что мы делали YouTube. Я не позволял себе рвать волосы, а говорил всем, что всё получится, потому что на самом деле всё давно просчитано.


Про производительность


Можете ли рассказать, сколько было максимально людей на сайте на одном треке? Были ли проблемы с производительностью?


Николай: Проблем с производительностью, как мы уже говорили, не было. Максимальное количество людей, которые были на одном докладе, 1300 человек, это на Heisenbug.


Были ли проблемы с локальным просмотром? И возможно ли техническое описание со схемами того, как это все устроено?


Николай: Сделаем об этом позже статью.


Локально можно отдебажить даже стримы. Как только начались конференции, это стало даже проще, потому что появились продакшен-стримы, которые мы можем смотреть постоянно.


Владимир: Как я понимаю, фронтенд-девелоперы локально работали с моками, а потом, поскольку время выкатки на дев во фронте тоже небольшое (5 минут), посмотреть, что там с сертификатами, проблем никаких нет.


Все тестируется, дебажится, даже локально. Значит, напишем статью со всеми техническими особенностями, покажем, расскажем все со схемами, как было.


Владимир: Сможете взять и повторить.


За 3 месяца.


Итог


Всё описанное вместе звучит круто с учётом того, что это сделано маленькой командой за три месяца.


Николай: Большая команда этого бы не сделала. А вот маленькая группа людей, которые довольно плотно и хорошо друг с другом общаются и могут договориться, могла бы. У них нет каких-то противоречий, архитектура была придумана за два дня, была финализирована и фактически не поменялась. Есть очень жесткая фасилитация поступающих бизнес-требований с точки зрения наваливания фич-реквестов и изменений.


Что оказалось в вашем списке дальнейших задач, когда летние конференции уже состоялись?


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


А ещё добавление всей платформе, кроме стримингового и конференционного, также постконференционное состояние. Это плейлисты (в том числе составленные пользователями), возможно, контент с других прошедших конференций, интегрированные, промаркированные, доступные для пользователя, ну и доступные для просмотра на нашем сайте (live.jugru.org).


Ребята, спасибо большое за ответы!




Если среди читателей есть те, кто был на наших летних конференциях поделитесь вашими впечатлениями от плеера и трансляции. Что было удобно, что раздражало, что хочется увидеть в будущем?


Если платформа заинтересовала и захотелось увидеть её в бою мы снова используем её на наших осенне-зимних конференциях. Их целый ряд, так что почти наверняка есть подходящая для вас.

Подробнее..

Из песочницы OBS Studio Lua Скриптинг

25.09.2020 18:15:34 | Автор: admin

Всем привет, в этом руководстве рассмотрим создание скриптов для OBS на языке Lua.


Скриптинг в OBS доступен начиная с версии 21, на данный момент новейшая 26.0.0-rc3 версия доступна для тестирования.Обновление включает в себя виртуальную веб камеру (пока что только на Windows), улучшенный UI, возможность скриншота любого источника( КДПВ была сделана с помощью этой функции).


image


Описание глобальных функций, API, настроек


Добавить скрипт можно через меню -> Инструменты -> Скрипты -> значок "плюс".
Скрипты могут быть добавлены, перезагружены, удалены в режиме реального времени.


Сходства и различия c С-API


Сходства: почти полный доступ к API, СБОЙ или УТЕЧКА ПАМЯТИ с неправильно написанным скриптом.


Различия: некоторые функции(с двойными указателями) недоступны, некоторые заменены на другие.


У каждого скрипта своё пространство имён, убедиться в этом можно открыв текущую коллекцию сцен "~/obs-studio/basic/scenes".


Настройки settings представляют собой JSON строку, они могут быть созданы/загружены/сохранены с помощью JSON строк или файлов.


Описание функций:


  • obslua модуль для доступа к функциям OBS
  • script_description() описание скрипта, поддерживает примитивный HTML
  • script_properties() пользовательский интерфейс
  • script_defaults(settings) устанавливает настройки по умолчанию
  • script_update(settings) вызывается каждый раз когда пользователь изменил настройки через пользовательский интерфейс
  • script_load(settings) загружает настройки при первом запуске
  • script_unload() вызывается при закрытии скрипта
  • script_save(settings) используется в основном для сохранения горячих клавиш, настройки c пользовательского интерфейса сохраняются автоматически
  • script_tick(seconds) вызывается каждый кадр, аргумент seconds получает значение потраченных секунд с предыдущего кадра
  • script_path() возвращает абсолютный путь к папке скрипта
  • timer_add(callback,milliseconds) вызов функции периодично
  • timer_remove(callback) удаление функции с таймера, также есть вариант использовать remove_current_callback() внутри функции которая вызывается периодично

Пример скрипта


Скрипт: Движение по линии с использованием кнопок и таймера.


local obs = obslualocal selected_sourcepos = obs.vec2()switch = falsecounter = 0

Короткая запись модуля, local var инициализация значения как nil, pos структура предоставляемая OBS для перемещения источников на сцене.


function script_properties()  local props = obs.obs_properties_create()  obs.obs_properties_add_button(props, "button1", "Вкл/Выкл",on_off)  obs.obs_properties_add_button(props, "button2", "Добавить источник",add_source)  obs.obs_properties_add_button(props, "button3", "Подвинуть источник на +10,0",move_button)  local p = obs.obs_properties_add_list(props, "selected_source", "Выберите источник", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)  local sources = obs.obs_enum_sources()  if sources ~= nil then    for _, source in ipairs(sources) do      source_id = obs.obs_source_get_unversioned_id(source)      if source_id == "color_source" then        local name = obs.obs_source_get_name(source)        obs.obs_property_list_add_string(p, name, name)      end    end  end  obs.source_list_release(sources)  return propsend

Добавляем пользовательский интерфейс. obs.obs_properties_add_button(props, "имя", "Описание",функция), local p = obs.obs_properties_add_list выпадающие меню с выбором источника, source_id = obs.obs_source_get_unversioned_id(source) получение имени источника при этом игнорируя его версию, obs.source_list_release(sources) освобождение памяти


function script_update(settings)  selected_source = obs.obs_data_get_string(settings,"selected_source")end

Обновление selected_source каждый раз когда настройки (выпадающее меню в этом случае) изменены.


function add_source()  current_scene = obs.obs_frontend_get_current_scene()  scene = obs.obs_scene_from_source(current_scene)  settings = obs.obs_data_create()  counter = counter + 1  green = 0xff00ff00  hotkey_data = nil  obs.obs_data_set_int(settings, "width",200)  obs.obs_data_set_int(settings, "height",200)  obs.obs_data_set_int(settings, "color",green)  source = obs.obs_source_create("color_source", "ист#" .. counter, settings, hotkey_data)  obs.obs_scene_add(scene, source)  obs.obs_scene_release(scene)  obs.obs_data_release(settings)  obs.obs_source_release(source)end

Выбор сцены и создание настроек для источника, добавление на сцену, освобождение памяти.


function move_source_on_scene()  current_scene = obs.obs_frontend_get_current_scene()  scene = obs.obs_scene_from_source(current_scene)  scene_item = obs.obs_scene_find_source(scene, selected_source)  if scene_item then    dx, dy = 10, 0    obs.obs_sceneitem_get_pos( scene_item, pos) -- обновить позицию если источник был перемещён мышкой    pos.x = pos.x + dx    pos.y = pos.y + dy    obs.obs_sceneitem_set_pos(scene_item, pos)   end  obs.obs_scene_release(scene)end

Функция перемещения источника в рамках сцены.


function move_button(props,p)  move_source_on_scene()end

Кнопка перемещения источника и 2 необходимых аргумента.


function on_off()  if switch then     obs.timer_add(move_source_on_scene,50)  else    obs.timer_remove(move_source_on_scene)  end  switch = not switchend

Кнопка переключатель и таймер периодического запуска функции в миллисекундах.
Гифка


Исходный код
local obs = obslualocal selected_sourcepos = obs.vec2()switch = falsecounter = 0function on_off()  if switch then     obs.timer_add(move_source_on_scene,50)  else    obs.timer_remove(move_source_on_scene)  end  switch = not switchendfunction add_source()  current_scene = obs.obs_frontend_get_current_scene()  scene = obs.obs_scene_from_source(current_scene)  settings = obs.obs_data_create()  counter = counter + 1  green = 0xff00ff00  hotkey_data = nil  obs.obs_data_set_int(settings, "width",200)  obs.obs_data_set_int(settings, "height",200)  obs.obs_data_set_int(settings, "color",green)  source = obs.obs_source_create("color_source", "ист#" .. counter, settings, hotkey_data)  obs.obs_scene_add(scene, source)  obs.obs_scene_release(scene)  obs.obs_data_release(settings)  obs.obs_source_release(source)endfunction move_button(props,p)  move_source_on_scene()endfunction move_source_on_scene()  current_scene = obs.obs_frontend_get_current_scene()  scene = obs.obs_scene_from_source(current_scene)  scene_item = obs.obs_scene_find_source(scene, selected_source)  if scene_item then    dx, dy = 10, 0    obs.obs_sceneitem_get_pos( scene_item, pos) -- обновить позицию если источник был перемещён мышкой    pos.x = pos.x + dx    pos.y = pos.y + dy    obs.obs_sceneitem_set_pos(scene_item, pos)   end  obs.obs_scene_release(scene)endfunction script_properties()  local props = obs.obs_properties_create()  obs.obs_properties_add_button(props, "button1", "Вкл/Выкл",on_off)  obs.obs_properties_add_button(props, "button2", "Добавить источник",add_source)  obs.obs_properties_add_button(props, "button3", "Cдвинуть источник на +10,0",move_button)  local p = obs.obs_properties_add_list(props, "selected_source", "Выберите источник", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)  local sources = obs.obs_enum_sources()  if sources ~= nil then    for _, source in ipairs(sources) do      source_id = obs.obs_source_get_unversioned_id(source)      if source_id == "color_source" then        local name = obs.obs_source_get_name(source)        obs.obs_property_list_add_string(p, name, name)      end    end  end  obs.source_list_release(sources)  return propsendfunction script_update(settings)  selected_source = obs.obs_data_get_string(settings,"selected_source")end

Пример горячих клавиш


Скрипт: Создание постоянных и изменяющихся горячих клавиш.


Создание изменяющихся горячих клавиш, в том смысле что их можно поменять в настройках OBS.


hotkeys = {  htk_stop = "Стоп",  htk_start = "Старт",}hk = {}function hotkey_mapping(hotkey)  if hotkey == "htk_stop" then    print('Стоп')  elseif hotkey == "htk_start" then    print('Старт')  endend

Словарь с клавишами и функция типа "switch"


function script_load(settings)  for k, v in pairs(hotkeys) do     hk[k] = obs.obs_hotkey_register_frontend(k, v, function(pressed)      if pressed then         hotkey_mapping(k)      end     end)    a = obs.obs_data_get_array(settings, k)    obs.obs_hotkey_load(hk[k], a)    obs.obs_data_array_release(a)  end  ...function script_save(settings)  for k, v in pairs(hotkeys) do    a = obs.obs_hotkey_save(hk[k])    obs.obs_data_set_array(settings, k, a)    obs.obs_data_array_release(a)  endend

Сохранение/загрузка изменяющихся горячих клавиш.


function htk_1_cb(pressed)   if pressed then    print('1')  endendfunction htk_2_cb(pressed)   if pressed then    print('2 активно')  else    print('2 не активно')  endendkey_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ],'key_2 = '"htk_2": [ { "key": "OBS_KEY_2" } ]}'json_s = key_1 .. key_2default_hotkeys = {  {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb},  {id='htk_2',des='Кнопка 2 ',callback=htk_2_cb},}

Создание постоянных клавиш, их можно поменять в настройках, но при перезапуске OBS они примут значения по умолчанию. В данном случае кнопку 1 и 2.


function script_load(settings)  ...  s = obs.obs_data_create_from_json(json_s)  for _,v in pairs(default_hotkeys) do     a = obs.obs_data_get_array(s,v.id)    h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback)    obs.obs_hotkey_load(h,a)    obs.obs_data_array_release(a)  end  obs.obs_data_release(s)end

Гифка


Исходный код
local obs = obsluahotkeys = {  htk_stop = "Стоп",  htk_start = "Старт",}hk = {}function hotkey_mapping(hotkey)  if hotkey == "htk_stop" then    print('Стоп')  elseif hotkey == "htk_start" then    print('Старт')  endendfunction htk_1_cb(pressed)   if pressed then    print('1')  endendfunction htk_2_cb(pressed)   if pressed then    print('2 активно')  else    print('2 не активно')  endendkey_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ],'key_2 = '"htk_2": [ { "key": "OBS_KEY_2" } ]}'json_s = key_1 .. key_2default_hotkeys = {  {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb},  {id='htk_2',des='Кнопка 2 ',callback=htk_2_cb},}function script_load(settings)  for k, v in pairs(hotkeys) do     hk[k] = obs.obs_hotkey_register_frontend(k, v, function(pressed)      if pressed then         hotkey_mapping(k)      end     end)    a = obs.obs_data_get_array(settings, k)    obs.obs_hotkey_load(hk[k], a)    obs.obs_data_array_release(a)  end  s = obs.obs_data_create_from_json(json_s)  for _,v in pairs(default_hotkeys) do     a = obs.obs_data_get_array(s,v.id)    h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback)    obs.obs_hotkey_load(h,a)    obs.obs_data_array_release(a)  end  obs.obs_data_release(s)endfunction script_save(settings)  for k, v in pairs(hotkeys) do    a = obs.obs_hotkey_save(hk[k])    obs.obs_data_set_array(settings, k, a)    obs.obs_data_array_release(a)  endend

Задачи


Задача на движение по кругу:
На основе скрипта движение по линии, создайте скрипт с движением вокруг часовой/против.


Гифка


Задача на использование кнопок клавиатуры:
На основе скрипта с горячими клавишами, создайте скрипт с переключателем вкл/выкл,
доп кнопкой через JSON, доп кнопкой с комбинацией клавиш через JSON.


Гифка


Ссылки


Подробнее..

Готовим видеосервис к нагрузке в сотни Гбитс. Доклад Яндекса

30.09.2020 12:15:28 | Автор: admin
Классический CDN anycast, GeoDNS, веб-сервер с кешем отлично работает с простыми файлами и небольшим количеством пользователей. Но если возникает необходимость раздавать потоковое видео, всё становится намного интереснее. Вместо одного короткого запроса появляется сессия, которая длится десятки минут. Без правильной балансировки пользователей и контента уже не прожить: кеша на всё не хватает, а когда Россия играет против Испании, это хотят смотреть сразу все. Руководитель разработки платформы видеостриминга Андрей Василенков рассказал, благодаря чему наш CDN позволяет обслуживать сотни тысяч пользовательских сессий одновременно и переживать отключения серверов и дата-центров. А в качестве бонуса показал на примере, как современная поп-культура мешает обучению.


Всем привет! Расскажу, какие вопросы приходится решать, когда вам нужно подготовить ваш сервис к нагрузкам в несколько сотен гигабит, а то и терабит в секунду. Впервые мы с такой проблемой столкнулись в 2018 году, когда готовились к трансляциям чемпионата мира по футболу.

Начнем с того, что вообще такое стриминговые протоколы и как они устроены самый поверхностный обзорный вариант.



В основе любого стримингового протокола лежит манифест [manifest] или плейлист [playlist]. Это небольшой текстовый файл, который содержит метаинформацию о контенте. Там описан тип контента live-трансляция или VoD-трансляция (video on demand). Например, в случае live это футбольный матч или онлайн-конференция, как у нас сейчас с вами, а в случае VoD ваш контент заранее подготовлен и лежит на ваших серверах, готовый к раздаче в сторону пользователей. В этом же файле описана длительность контента, информация о DRM.



Там же описаны вариации контента видеодорожки, аудиодорожки, субтитры. Видеодорожки могут быть представлены в разных кодеках. Например, универсальный H.264 поддерживается на любом устройстве. С его помощью вы сможете проиграть видео на любом утюге у вас дома. Или есть более современные и более эффективные кодеки HEVC и VP9, которые позволяют вам передавать картинку 4K с поддержкой HDR.

Аудиодорожки тоже могут быть представлены в разных кодеках с разными битрейтами. А еще их может быть несколько оригинальная аудиодорожка фильма на английском языке, перевод на русский язык, интершум или, например, записьспортивного события напрямую со стадиона без комментаторов.



Что со всем этим делает плеер? Задача плеера в первую очередь выбрать те вариации контента, которые он может проиграть, просто потому что не все кодеки универсальны, не все могут быть проиграны на определенном устройстве.

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

Также на этом этапе он выбирает аудиодорожку, с которой он будет начинать проигрывание. Предположим, у вас в операционной системе стоит английский язык. Тогда он может выбрать по умолчанию английскую аудиодорожку. Наверное, вам так будет удобнее.

После этого он начинает формировать ссылки на видео- и аудиосегменты. На самом деле это обычные HTTP-ссылки, такие же, как во всех остальных сценариях в интернете. И он начинает скачивать видео- и аудиосегменты, складывать их в буфер друг за другом и бесшовно проигрывать. Такие видеосегменты, как правило, имеют длительность 2, 4, 6 секунд, может быть, 10 секунд в зависимости от вашего сервиса.



Какие тут есть важные моменты, про которые нам нужно думать, когда мы проектируем наш CDN? В первую очередь, у нас появляется сессия пользователя.

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

Тут важно понимать, что время ответа сервера тоже имеет значение. Если мы показываем какую-нибудь live-трансляцию в реальном времени, то не можем делать большой буфер просто потому, что пользователь хочет смотреть видео настолько близко к реальному времени, насколько возможно. Ваш буфер в принципе не может быть большим. Соответственно, если сервер не успевает отвечать за то время, пока пользователь успевает просматривать контент, видео в какой-то момент просто зависнет. К тому же контент довольно тяжеловесный. Стандартный битрейт для Full HD 1080p 3-5 Мбит/с. Соответственно, на одном гигабитовом сервере вы не сможете обслужить больше 200 пользователей одновременно. И это идеальная картинка, потому что пользователи, как правило, равномерно по времени со своими запросами не ходят.



В какой момент пользователь вообще взаимодействует с вашим CDN? Взаимодействие происходит в основном в двух местах: когда плеер скачивает манифест (плейлист), и когда он скачивает сегменты.

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

Задача всей нашей системы сводится к тому, что мы хотим сформировать правильную ссылку на эти сегменты и подставить туда правильный домен какого-нибудь нашего CDN-хоста. В этом месте мы пользуемся следующей стратегией: сразу в плейлисте отдаем нужный CDN-хост, куда пользователь пойдет. Этот подход лишен многих недостатков, но обладает одним важным нюансом. Вам нужно гарантировать, что у вас есть механизм, который позволит увести пользователя с одного хоста на другой бесшовно в процессе проигрывания, не прерывая просмотр. На самом деле такая возможность есть у всех современных стриминговых протоколов, и HLS, и DASH такое поддерживают. Нюанс: довольно часто даже в очень популярных опенсорс-библиотеках такая возможность не реализована, хоть и существует по стандарту. Нам самим приходилось посылать пачки в опенсорс-библиотеку Shaka, она джаваскриптовая, используется для веб-плеера, для проигрывания DASH.

Есть еще одна схема anycast-схема, когда вы используете один единый домен и отдаете во всех ссылках именно его. В этом случае вам не нужно думать ни про какие нюансы, отдаете один домен, и все счастливы. (...)



Теперь давайте поговорим про то, как мы будем формировать наши ссылки.

С точки зрения сети любая крупная компания устроена как автономная система, и часто даже не одна. На самом деле автономная система это система IP-сетей и маршрутизаторов, которые управляются единым оператором и обеспечивают единую политику маршрутизации с внешней сетью, с интернетом. Яндекс тут не исключение. Сеть Яндекса тоже автономная система, и связь с другими автономными системами происходит за пределами дата-центров Яндекса в точках присутствия. В эти точки присутствия приходят физические кабели Яндекса, физические кабели других операторов, и они коммутируются на месте, на железном оборудовании. Именно в таких точках у нас есть возможность поставить несколько своих серверов, жесткие диски, SSD. Именно туда мы и будем направлять трафик пользователей.

Этот набор серверов мы будем называть локацией. И в каждой такой локации у нас есть уникальный идентификатор. Мы его будем использовать в составе доменного имени хостов на этой площадке и просто чтобы однозначно ее идентифицировать.

Таких площадок в Яндексе несколько десятков, серверов на них несколько сотен, и в каждую локацию приходят линки от нескольких операторов, поэтому линков у нас тоже порядка нескольких сотен.

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



На этом этапе вариантов не очень много. Мы можем использовать только IP-адрес, чтобы принимать решения. С этим нам помогает отдельная команда Яндекса Traffic Team, которая знает все про то, как устроен трафик и сеть в компании, и именно она собирает маршруты других операторов, чтобы мы использовали эти знания в процессе балансировки пользователей.

Набор маршрутов она собирает с помощью BGP. Про BGP подробно говорить не будем, это протокол, который позволяет участникам сети на границах своих автономных систем анонсировать, какие же маршруты их автономная система может обслужить. Traffic Team собирает всю эту информацию, агрегирует, анализирует и строит полную карту всей сети, которой мы и пользуемся для балансировки.

Мы получаем от команды Traffic Team набор IP-сетей и линков, через которые мы можем обслуживать клиентов. Дальше нам нужно понять, какая же IP-подсеть подходит конкретному пользователю.



Делаем это довольно простым способом строим префиксное дерево. А дальше наша задача используя в качестве ключа IP-адрес пользователя, найти, какая подсеть наиболее точно соответствует этому IP-адресу.



Когда мы ее нашли, у нас есть список линков, их веса, и по линкам мы можем однозначно определить ту локацию, куда отправим пользователя.



Что такое вес в этом месте? Это метрика, которая позволяет управлять распределением пользователей по разным локациям. У нас могут быть линки, например, разной емкости. У нас может быть 100-гигабитный линк и 10-гигабитный линк на одной площадке. Очевидно, что в первый линк мы хотим отправлять больше пользователей, потому что он более емкий. Этот вес учитывает топологию сети, потому что интернет сложный граф связанного между собой сетевого оборудования, трафик у вас может пойти по разным путям, и эту топологию тоже нужно учитывать.

Обязательно нужно смотреть, как происходит реальное скачивание данных пользователями. Это можно делать и на серверной, и на клиентской стороне. На сервере мы активно собираем в логах TCP info пользовательских соединений, смотрим на round-trip time. С пользовательской стороны мы активно собираем perf-логи браузера и плеера. В этих perf-логах есть подробная информация о том, как происходило скачивание файлов с нашего CDN.

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



Допустим, мы выбрали линк. Можем ли мы прямо на этом этапе отправлять туда пользователей? Не можем, потому что вес довольно статичен на протяжении долгого периода времени, и он не учитывает никакую реальную динамику нагрузки. Мы хотим в реальном времени определять, можем ли мы сейчас использовать линк, загруженный, скажем, на 80%, когда рядом есть чуть менее приоритетный линк, загруженный всего на 10%. Скорее всего, в этом случае мы как раз захотим использовать второй.



Что еще нужно принимать во внимание в этом месте? Мы должны учитывать пропускную способность линка, понимать его текущий статус. Он может работать или быть технически неисправным. Или, может быть, мы его хотим увести в сервис, чтобы не пускать туда пользователей и обслуживать его, расширить, например. Мы всегда должны учитывать текущую нагрузку этого линка.

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

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

В нашем CDN есть и другие пользователи. Мы не единственный сервис, который пользуется этими раздающими машинками. И на фоне нашей нагрузки нагрузка других сервисов не такая значительная. Но даже на нашем фоне она бывает довольно-таки заметной. Их раздачи проходят не через наш контур, поэтому мы не можем управлять этим трафиком.

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



Допустим, мы посчитали метрики, всё собрали. Теперь нужен алгоритм принятия решения при балансировке. Он должен обладать четырьмя важными свойствами:

Обеспечивать пропускную способность линка.
Предупреждать перегрузку линка, просто потому что если вы загрузили линк на 95% или 98%, то у вас начинают переполняться буферы на сетевом оборудовании, начинаются дропы пакетов, ретрансмиты, и пользователи ничего хорошего от этого не получают.
Предупреждать пил нагрузки, про это поговорим чуть позже.
В идеальном мире было бы здорово, чтобы мы научились утилизировать линк до определенного уровня, который мы считаем правильным. Например, 85% загрузки.



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

Что мы с ними будем делать? Введем по одной вероятностной величине на каждый такой класс сессии. У нас будет величина под названием Slowdown, определяющая процент новых сессий, которые мы не будем пускать на этот линк. Если Slowdown равен нулю, то мы все новые сессии принимаем, а если он равен 50%, то каждую, грубо говоря, вторую сессию мы отказываемся обслуживать на этом линке. При этом наш алгоритм балансировки на более высоком уровне будет проверять альтернативные варианты для этого пользователя. Drop то же самое, только для текущих сессий. Мы можем часть пользовательских сессий увести с площадки куда-нибудь в другое место.



Как мы будем выбирать, каким будет значение наших вероятностных метрик? В качестве основы возьмем процент загрузки линка, а дальше первая наша идея была такой: давайте воспользуемся кусочно-линейной интерполяцией.

Мы взяли такую функцию, которая имеет несколько точек преломления, и по ней смотрим значение наших коэффициентов. Если уровень загрузки линка минимальный, то все хорошо, Slowdown и Drop равны нулю, мы пускаем всех новых пользователей. Как только уровень загрузки переходит через некоторый порог, мы начинаем части пользователей отказывать в обслуживании на этом линке. В какой-то момент, если нагрузка продолжает расти, мы просто перестаем пускать новые сессии.

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

Тем не менее, загрузка может продолжать расти. В какой-то момент мы можем начать уводить часть сессий или даже полностью снять нагрузку с этого линка.

Именно в таком виде мы и запустили этот алгоритм на первых матчах чемпионата мира по футболу. Наверное, интересно посмотреть, какую картинку мы увидели. Она была примерно следующей.



Даже невооруженным глазом сторонний наблюдатель может понять, что тут что-то, наверное, не так, и спросить меня: Андрей, все ли у вас хорошо?. А если бы вы были моим начальником, вы бы бегали по комнате и кричали: Андрей, боже мой! Откатывайте все назад! Верните все как было! Давайте расскажу, что тут происходит.

По оси X время, по оси Y мы наблюдаем за уровнем нагрузки линков. Тут изображены два линка, которые обслуживают одну и ту же площадку. Важно понимать, что в этот момент мы пользовались только той схемой наблюдения за загрузкой линка, которая снимается с сетевого оборудования, и поэтому не могли быстро реагировать на динамику нагрузки.

Когда мы отправляем пользователей в какой-то из линков, происходит резкий рост трафика на этом линке. Линк перегружается. Мы снимаем нагрузку и оказываемся в правой части функции, которую видели на предыдущем графике. И мы начинаем сбрасывать старых пользователей и перестаем пускать новых. Им нужно куда-то идти, а идут они, конечно же, на соседний линк. В прошлый раз он, возможно, был менее приоритетным, а теперь он у них в приоритете.

На втором линке повторяется та же картинка. Мы резко повышаем нагрузку, замечаем, что линк перегружен, снимаем нагрузку, и эти два линка оказываются в противофазе по уровню нагрузки.



Что можно сделать? Мы можем проанализировать динамику системы, при большом росте нагрузки замечать это и немного ее демпфировать. Именно это мы и сделали. Мы взяли текущий момент, взяли окно наблюдений в прошлое за несколько минут, например 2-3 минуты, и посмотрели, насколько сильно меняется загрузка линка на этом интервале. Разницу между минимальным и максимальным значением мы будем называть интервалом колебаний этого линка. И если этот интервал колебаний большой, мы добавим демпфирование, таким образом увеличим наш Slowdown и станем пускать меньше сессий.



Выглядит эта функция примерно так же, как и прошлая, с чуть меньшим числом переломов. Если у нас интервал загрузки колебаний небольшой, то никакого extra_slowdown мы добавлять не будем. А если интервал колебаний начинает расти, то extra_slowdown принимает ненулевые значения, позже мы будем прибавлять его к основному Slowdown.



Такая же логика работает и при низких значениях интервала колебаний. Если у вас колебания на линке минимальные, то вы, возможно, наоборот, хотите пустить туда немножко больше пользователей, снизить Slowdown и тем самым лучше утилизировать ваш линк.



Эту часть мы тоже внедрили. Итоговая формула имеет примерно следующий вид. При этом мы гарантируем, что обе эти величины extra_slowdown и reduce_slowdown никогда не имеют ненулевого значения одновременно, поэтому эффективно работает только одна из них. Именно в таком виде эта формула балансировки пережила все топовые матчи чемпионата мира по футболу. Даже на самых популярных матчах она работала довольно хорошо: Это Россия Хорватия, Россия Испания. Во время этих матчей мы раздавали рекордные для Яндекса объемы трафика 1,5 терабита в секунду. Мы спокойно это пережили. С тех пор формула никак не менялась, потому что такого трафика на нашем сервисе с тех пор не было до определенного момента.

Потом к нам пришла пандемия. Людей отправили сидеть домой, а дома есть хороший интернет, телевизор, планшет и много свободного времени. Трафик на наши сервисы стал органично расти, довольно быстро и значимо. Сейчас такого рода нагрузки, как были во время чемпионата мира по футболу, наша ежедневная рутина. Мы с тех пор немного расширили наши каналы с операторами, но, тем не менее, начали задумываться о следующей итерации нашего алгоритма, о том, какой она должна быть и как нам лучше утилизировать нашу сеть.



Какие есть недостатки у нашего предыдущего алгоритма? Мы не решили две проблемы. Мы не избавились полностью от пил нагрузок. Мы очень сильно улучшили картинку и амплитуда этих колебаний минимальна, период сильно увеличился, что тоже позволяет лучше утилизировать сеть. Но все равно они временами появляются, остаются. Мы не научились утилизировать сеть до того уровня, до какого хотели бы. Например, у нас нет возможности с помощью конфигурации задать желаемый максимальный уровень нагрузки линка в 80-85%.



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

Но тут есть два нюанса. Первый в Яндексе не принято писать единые места принятия решений, просто потому что при наших уровнях нагрузки, при нашем трафике, такое место быстро становится узким местом.

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



Нам обязательно нужны быстрые метрики. Без них единственное, что вы можете сделать, избежав страданий пользователя, недоутилизировать сеть. Но это нас тоже не устраивает.

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



Мы посмотрели на фильтр Калмана. Это такая крутая штука, которая позволяет построить математическую модель системы и при зашумленных метриках или при отсутствии некоторых классов метрик улучшить модель с помощью вашей реальной системы. И потом принимать решение о реальной системе, основываясь на математической модели. К сожалению, оказалось, что у нас не так много классов метрик, которые мы можем использовать, и не получается этот алгоритм применить.



Мы подошли с другой стороны, взяли за основу другой компонент этой теории PID-регулятор. Он ничего не знает про вашу систему. Его задача знать идеальное состояние системы, то есть наш желаемый уровень загрузки, и текущее состояние системы, например уровень нагрузки. Разницу между двумя этими состояниями он считает ошибкой и с помощью своих внутренних алгоритмов управляет контрольным сигналом, то есть нашими значениями Slowdown и Drop. Его цель минимизировать ошибку, которая есть в системе.

Со дня на день мы попробуем этот PID-регулятор в продакшене. Возможно, через несколько месяцев сможем рассказать вам о результатах.

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



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

У меня есть еще одна интересная история. Весной, как вы знаете, начался карантин. У Яндекса давно есть образовательная платформа Яндекс.Учебник, которая позволяет учителям загружать ролики, уроки. Школьники туда приходят и смотрят контент. Во время пандемии Яндекс начал поддерживать школы, активно звать их на свою платформу, чтобы школьники могли обучаться удаленно. И мы в какой-то момент увидели довольно хороший рост трафика, довольно стабильную картинку. Но в один из апрельских вечеров мы увидели на графиках примерно следующее.



Снизу картинка трафика на образовательном контенте. Мы увидели, что он в какой-то момент резко упал. Начали паниковать, выяснять, что вообще происходит, что у нас сломалось. Потом мы заметили, что общий трафик на сервис при этом начал расти. Очевидно, случилось что-то интересное.

На самом деле в этот момент произошло следующее.



Вот как быстро танцует человечек.

Начался концерт Little Big, и все школьники ушли смотреть его. Но после окончания концерта они вернулись и с успехом продолжили обучаться дальше. Такие картинки мы довольно часто наблюдаем на нашем сервисе. Поэтому, думаю, работа у нас довольно интересная. Всем спасибо! На этом про CDN я, наверное, закончу.
Подробнее..

OBS Studio Lua Скриптинг. Часть 2

06.10.2020 16:11:14 | Автор: admin

Всем привет, в этой части руководства рассмотрим:
фильтры, сцены, предметы сцен, Frontend API, создание функциональных фильтров и прочее
С первой частью можно ознакомиться по этой ссылке.


КДПВ сделана в OBS 26.0.0


Краткая справка для этой части


  • Источник Источники используются для рендера аудио/видео, например: захват камеры, игры, звука. С помощью источников можно создавать фильтры, переходы


  • Фильтр Источник который дополняет другие источники


  • Сцены Коллекция источников, сцена является источником ( сцену можно добавить как источник в другой сцене)


  • Предмет сцены конкретный источник в сцене, его можно: перемещать, увеличивать/уменьшать, переворачивать, менять состояние выкл/вкл и.т.д


  • Frontend API Набор функций который предоставляет OBS Studio, например:


    • подписка на событие о переключении сцен
    • запрос статуса о том, идёт ли стрим/запись
    • вкл/выкл стрим/запись
    • переключение сцен


Фильтры


Типы фильтров так же как и источников, можно узнать через функцию obs_source_get_unversioned_id


Название Внутреннее представление типа
Компрессор compressor_filter
Экспандер expander_filter
Усиление gain_filter
Инвертировать полярность invert_polarity_filter
Лимитер limiter_filter
Пропускной уровень шума noise_gate_filter
Шумоподавление noise_suppress_filter
VST 2.x плагин vst_filter
Задержка видео (асинхронность) async_delay_filter
Хромакей chroma_key_filter
Коррекция цвета color_filter
Цветовой ключ color_key_filter
Кадрирование crop_filter
Маска изображения/Смешивание mask_filter
Яркостный ключ luma_key_filter
Задержка отображения gpu_delay
Масштабирование/Соотношение сторон scale_filter
Прокрутка scroll_filter
Увеличить резкость sharpness_filter

В английском варианте: ссылка


Скрипт: изменение параметра прозрачности у фильтра на случайную величину от 1 до 100.


Чтобы узнать название параметра "прозрачность" необходимо добавить фильтр с прозрачностью на какой-нибудь источник, изменить этот параметр. Далее открыть файл коллекции сцен, путь к директории можно узнать через меню OBS:
Справка > Файлы журнала > Показать файлы журнала
далее с этой директории поднимаемся выше, и получаем путь ~/basic>scenes>название_сцены.json
В этом файле ищем color_filter или color_key_filter (оба фильтра могут изменить прозрачность источника).
В строке settings видим что прозрачность записана как opacity.
Ещё один способ узнать название параметра, прочитать исходный код фильтра ссылка


Находим источник по имени


function add_filter_to_source(random_n)  source = obs.obs_get_source_by_name(source_name)

Создаём настройки с изменением параметра opacity на случайное число


settings = obs.obs_data_create()obs.obs_data_set_int(settings, "opacity",random_n)

Проверяем существует ли уже фильтр на источнике, если нет добавляем


_color_filter = obs.obs_source_get_filter_by_name(source,"opacity_random")if _color_filter == nil then -- if not exists  _color_filter = obs.obs_source_create_private( "color_filter", "opacity_random", settings)  obs.obs_source_filter_add(source, _color_filter)end

Обновляем и освобождаем память


  obs.obs_source_update(_color_filter,settings)  obs.obs_source_release(source)  obs.obs_data_release(settings)  obs.obs_source_release(_color_filter)end

Привязка к горячей клавише


function htk_1_cb(pressed)   if pressed then    n = math.random(1,100)    add_filter_to_source(n)  endend

Гифка


Исходный код
local obs = obsluasource_name = ''function htk_1_cb(pressed)   if pressed then    n = math.random(1,100)    add_filter_to_source(n)  endendfunction add_filter_to_source(random_n)  source = obs.obs_get_source_by_name(source_name)  settings = obs.obs_data_create()  obs.obs_data_set_int(settings, "opacity",random_n)  _color_filter = obs.obs_source_get_filter_by_name(source,"opacity_random")  if _color_filter == nil then -- if not exists    _color_filter = obs.obs_source_create_private( "color_filter", "opacity_random", settings)    obs.obs_source_filter_add(source, _color_filter)  end  obs.obs_source_update(_color_filter,settings)  obs.obs_source_release(source)  obs.obs_data_release(settings)  obs.obs_source_release(_color_filter)endfunction script_properties()  -- source https://raw.githubusercontent.com/insin/obs-bounce/master/bounce.lua  local props = obs.obs_properties_create()  local source = obs.obs_properties_add_list(    props,    'source',    'Source:',    obs.OBS_COMBO_TYPE_EDITABLE,    obs.OBS_COMBO_FORMAT_STRING)  for _, name in ipairs(get_source_names()) do    obs.obs_property_list_add_string(source, name, name)  end  return propsendfunction script_update(settings)  source_name = obs.obs_data_get_string(settings, 'source')end--- get a list of source names, sorted alphabeticallyfunction get_source_names()  local sources = obs.obs_enum_sources()  local source_names = {}  if sources then    for _, source in ipairs(sources) do      -- exclude Desktop Audio and Mic/Aux by their capabilities      local capability_flags = obs.obs_source_get_output_flags(source)      if bit.band(capability_flags, obs.OBS_SOURCE_DO_NOT_SELF_MONITOR) == 0 and        capability_flags ~= bit.bor(obs.OBS_SOURCE_AUDIO, obs.OBS_SOURCE_DO_NOT_DUPLICATE) then        table.insert(source_names, obs.obs_source_get_name(source))      end    end  end  obs.source_list_release(sources)  table.sort(source_names, function(a, b)    return string.lower(a) < string.lower(b)  end)  return source_namesendkey_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ]}'json_s = key_1default_hotkeys = {  {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb},}function script_load(settings)  s = obs.obs_data_create_from_json(json_s)  for _,v in pairs(default_hotkeys) do     a = obs.obs_data_get_array(s,v.id)    h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback)    obs.obs_hotkey_load(h,a)    obs.obs_data_array_release(a)  end  obs.obs_data_release(s)end

Стоит упомянуть также о функции obs_source_enum_filters с её помощью можно получить
список всех фильтров у конкретного источника, кстати эта функция не работает в obspython,
но об этом чуть позже.


function check()  source = obs.obs_get_source_by_name(source_name)  result = obs.obs_source_enum_filters(source)  for k,v in pairs(result) do     name = obs.obs_source_get_name(v)    print('name'.. name)  end  obs.source_list_release(result)  obs.obs_source_release(source)end

Эвенты и состояние


Скрипт: звуковое оповещение о том что сцена изменена, с использованием .mp3 файла.
На основе этого скрипта


Создадим функцию для проигрывания звука при смене сцен.


function on_event(event)   if event == obs.OBS_FRONTEND_EVENT_SCENE_CHANGED    then obs_play_sound_release_source()  end end

Добавим источник медиа, установим настройки: файл alert.mp3 относителен директории нахождения
скрипта, obs_source_set_monitoring_type выставляет прослушивание аудио.


function play_sound()  mediaSource = obs.obs_source_create_private("ffmpeg_source", "Global Media Source", nil)  local s = obs.obs_data_create()  obs.obs_data_set_string(s, "local_file",script_path() .. "alert.mp3")  obs.obs_source_update(mediaSource,s)  obs.obs_source_set_monitoring_type(mediaSource,obs.OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT)  obs.obs_data_release(s)  obs.obs_set_output_source(outputIndex, mediaSource)  return mediaSourceendfunction obs_play_sound_release_source()  r = play_sound()  obs.obs_source_release(r)end

Исходный код
local obs = obsluamediaSource = nil -- Null pointeroutputIndex = 63 -- Last indexfunction play_sound()  mediaSource = obs.obs_source_create_private("ffmpeg_source", "Global Media Source", nil)  local s = obs.obs_data_create()  obs.obs_data_set_string(s, "local_file",script_path() .. "alert.mp3")  obs.obs_source_update(mediaSource,s)  obs.obs_source_set_monitoring_type(mediaSource,obs.OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT)  obs.obs_data_release(s)  obs.obs_set_output_source(outputIndex, mediaSource)  return mediaSourceendfunction obs_play_sound_release_source()  r = play_sound()  obs.obs_source_release(r)endfunction on_event(event)   if event == obs.OBS_FRONTEND_EVENT_SCENE_CHANGED    then obs_play_sound_release_source()  end endfunction script_load(settings)  obs.obs_frontend_add_event_callback(on_event)endfunction script_unload()  obs.obs_set_output_source(outputIndex, nil)end

Время и файлы


Запись в файл, "a" создаст(если нет) файл и добавит "content", а "w" перезапишет .


io.output(io.open(script_path() .. "out.txt","a"))io.write("content")io.close()

print(os.date("%c"))-- День недели Месяц Время Год


Сцены и предметы сцен


  • obs_sceneitem_get_source предметы сцен в источник
  • obs_scene_from_source преобразование сцены в источник
  • obs_scene_find_source преобразование источника в предмет сцены
  • obs_frontend_get_scenes получение всех сцен, освобождать с source_list_release
  • obs_frontend_get_current_scene получение текущей сцены
  • obs_scene_enum_items список всех предметов в сцене, освобождать с sceneitem_list_release

Скрипт: включение и выключение предмета сцены(источника на сцене).


Получение всех сцен и предметов в них


function toggle_source()  scenes = obs.obs_frontend_get_scenes()  for _,scene in pairs(scenes) do    scene_source = obs.obs_scene_from_source(scene)    items = obs.obs_scene_enum_items(scene_source)...

Поиск конкретного источника и его включение или выключение, source_name и boolean определены глобально.


...for _,scene_item in pairs(items) do  _source = obs.obs_sceneitem_get_source(scene_item)  _name = obs.obs_source_get_name(_source)  if _name == source_name then    boolean = not boolean     obs.obs_sceneitem_set_visible(scene_item, boolean)  endend...

Гифка


Исходный код
local obs = obsluasource_name = ''boolean = truefunction htk_1_cb(pressed)   if pressed then    toggle_source()  endendfunction toggle_source()  scenes = obs.obs_frontend_get_scenes()  for _,scene in pairs(scenes) do    scene_source = obs.obs_scene_from_source(scene)    items = obs.obs_scene_enum_items(scene_source)    for _,scene_item in pairs(items) do      _source = obs.obs_sceneitem_get_source(scene_item)      _name = obs.obs_source_get_name(_source)      if _name == source_name then        boolean = not boolean         obs.obs_sceneitem_set_visible(scene_item, boolean)      end    end    obs.sceneitem_list_release(items)  end  obs.source_list_release(scenes)endfunction script_properties()  -- source https://raw.githubusercontent.com/insin/obs-bounce/master/bounce.lua  local props = obs.obs_properties_create()  local source = obs.obs_properties_add_list(    props,    'source',    'Source:',    obs.OBS_COMBO_TYPE_EDITABLE,    obs.OBS_COMBO_FORMAT_STRING)  for _, name in ipairs(get_source_names()) do    obs.obs_property_list_add_string(source, name, name)  end  obs.obs_property_set_long_description(source,"?" )  return propsendfunction script_update(settings)  source_name = obs.obs_data_get_string(settings, 'source')end--- get a list of source names, sorted alphabeticallyfunction get_source_names()  local sources = obs.obs_enum_sources()  local source_names = {}  if sources then    for _, source in ipairs(sources) do      -- exclude Desktop Audio and Mic/Aux by their capabilities      local capability_flags = obs.obs_source_get_output_flags(source)      if bit.band(capability_flags, obs.OBS_SOURCE_DO_NOT_SELF_MONITOR) == 0 and        capability_flags ~= bit.bor(obs.OBS_SOURCE_AUDIO, obs.OBS_SOURCE_DO_NOT_DUPLICATE) then        table.insert(source_names, obs.obs_source_get_name(source))      end    end  end  obs.source_list_release(sources)  table.sort(source_names, function(a, b)    return string.lower(a) < string.lower(b)  end)  return source_namesendkey_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ]}'json_s = key_1default_hotkeys = {  {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb},}function script_load(settings)  s = obs.obs_data_create_from_json(json_s)  for _,v in pairs(default_hotkeys) do     a = obs.obs_data_get_array(s,v.id)    h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback)    obs.obs_hotkey_load(h,a)    obs.obs_data_array_release(a)  end  obs.obs_data_release(s)end

Регистрация фильтров


В obslua доступна функция obs_register_source, с её помощью можно зарегистрировать
источник( переходы и фильтры это источники). Для этого понадобится создать таблицу источника
Регистрация фильтров удобна тем, что позволяет закрепить функциональность скрипта за
определенным источником. Поддерживает горячие клавиши, интерфейс, таймеры.


Скрипт: закрепление горячих клавиш на фильтре, и полный доступ к источнику.


Импорт библиотеки, и определение типа как источник-фильтр.


local obs = obslualocal bit = require("bit")local info = {} -- obs_source_info https://obsproject.com/docs/reference-sources.htmlinfo.id = "uniq_filter_id"info.type = obs.OBS_SOURCE_TYPE_FILTERinfo.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO)info.get_name = function() return 'default filter name' end

Инициализация фильтра, будет вызываться при запуске программы или при добавлении к источнику


info.create = function(settings,source)   local filter = {}  filter.context = source

Начальная регистрация горячих клавиш, принадлежащих конкретному фильтру.


filter.hotkeys = {  htk_stop = "[stop] ",  htk_restart = "[start] ",}filter.hotkey_mapping = function(hotkey,data)  if hotkey == "htk_stop" then    print('stop '.. data.srsn .. " : " .. data.filn)  elseif hotkey == "htk_restart" then    print('restart ' .. data.srsn .. " : " .. data.filn)  endendfilter.hk = {}for k,v in pairs(filter.hotkeys) do   filter.hk[k] = obs.OBS_INVALID_HOTKEY_IDend

Создание функции которая запустится не сразу ( это необходимо т.к фильтр ещё не создан)
Он будет создан после return


filter._reg_htk = function()    info.reg_htk(filter,settings)  end  obs.timer_add(filter._reg_htk,100) -- callback to register hotkeys, one time only

Завершающая регистрация горячих клавиш,obs_filter_get_parent источник который фильтруется
к которому прикреплён фильтр этого типа. Удаление таймера.


info.reg_htk = function(filter,settings) -- register hotkeys after 100 ms since filter was created  local target = obs.obs_filter_get_parent(filter.context)  local srsn = obs.obs_source_get_name(target)   local filn =  obs.obs_source_get_name(filter.context)  local data = {srsn = srsn, filn = filn}   for k, v in pairs(filter.hotkeys) do     filter.hk[k] = obs.obs_hotkey_register_frontend(k, v .. srsn .. " : " .. filn, function(pressed)    if pressed then filter.hotkey_mapping(k,data) end end)    local a = obs.obs_data_get_array(settings, k)    obs.obs_hotkey_load(filter.hk[k], a)    obs.obs_data_array_release(a)  end  obs.remove_current_callback()end

Необходимый код для пропуска фильтрации, без него при добавлении фильтра источник "выключится"


info.video_render = function(filter, effect)   -- called every frame  local target = obs.obs_filter_get_parent(filter.context)  if target ~= nil then    filter.width = obs.obs_source_get_base_width(target)    filter.height = obs.obs_source_get_base_height(target)  end  obs.obs_source_skip_video_filter(filter.context) endinfo.get_width = function(filter)  return filter.widthendinfo.get_height = function(filter)  return filter.heightend

Функция .save вызывается при сохранении настроек, т.е можно переназначить горячие клавиши.
obs.obs_register_source(info) регистрация фильтра, теперь его видно при нажатии ПКМ


info.save = function(filter,settings)  for k, v in pairs(filter.hotkeys) do    local a = obs.obs_hotkey_save(filter.hk[k])    obs.obs_data_set_array(settings, k, a)    obs.obs_data_array_release(a)  endendobs.obs_register_source(info)

info.load также как и script_load, вызывается при запуске программы, но в данном
случае дублирует функциональность и требует перезапуска. .update, .get_properties
функции аналогичные script_update, script_properties.


Гифка


Исходный код
local obs = obslualocal bit = require("bit")local info = {} -- obs_source_info https://obsproject.com/docs/reference-sources.htmlinfo.id = "uniq_filter_id"info.type = obs.OBS_SOURCE_TYPE_FILTERinfo.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO)info.get_name = function() return 'default filter name' endinfo.create = function(settings,source)   local filter = {}  filter.context = source  filter.hotkeys = {    htk_stop = "[stop] ",    htk_restart = "[start] ",  }  filter.hotkey_mapping = function(hotkey,data)    if hotkey == "htk_stop" then      print('stop '.. data.srsn .. " : " .. data.filn)    elseif hotkey == "htk_restart" then      print('restart ' .. data.srsn .. " : " .. data.filn)    end  end  filter.hk = {}  for k,v in pairs(filter.hotkeys) do     filter.hk[k] = obs.OBS_INVALID_HOTKEY_ID  end  filter._reg_htk = function()    info.reg_htk(filter,settings)  end  obs.timer_add(filter._reg_htk,100) -- callback to register hotkeys, one time only  return filterendinfo.reg_htk = function(filter,settings) -- register hotkeys after 100 ms since filter was created  local target = obs.obs_filter_get_parent(filter.context)  local srsn = obs.obs_source_get_name(target)   local filn =  obs.obs_source_get_name(filter.context)  local data = {srsn = srsn, filn = filn}   for k, v in pairs(filter.hotkeys) do     filter.hk[k] = obs.obs_hotkey_register_frontend(k, v .. srsn .. " : " .. filn, function(pressed)    if pressed then filter.hotkey_mapping(k,data) end end)    local a = obs.obs_data_get_array(settings, k)    obs.obs_hotkey_load(filter.hk[k], a)    obs.obs_data_array_release(a)  end  obs.remove_current_callback()endinfo.video_render = function(filter, effect)   -- called every frame  local target = obs.obs_filter_get_parent(filter.context)  if target ~= nil then    filter.width = obs.obs_source_get_base_width(target)    filter.height = obs.obs_source_get_base_height(target)  end  obs.obs_source_skip_video_filter(filter.context) endinfo.get_width = function(filter)  return filter.widthendinfo.get_height = function(filter)  return filter.heightend--info.load = function(filter,settings) -- restart required--... same code as in info.reg_htk, but filters will be created from scratch every time--obs restarts, there is no reason to define it here again becuase hotkeys will be duplicated--endinfo.save = function(filter,settings)  for k, v in pairs(filter.hotkeys) do    local a = obs.obs_hotkey_save(filter.hk[k])    obs.obs_data_set_array(settings, k, a)    obs.obs_data_array_release(a)  endendobs.obs_register_source(info)

obspython


В OBS также доступен скриптинг через Python, для Windows только 3.6 версия, для Linux встроенная (т.к в настройках нельзя указать путь),
для MacOS Python не доступен для текущей (26.0.0) версии.
В отличии от Lua тут нельзя регистрировать источники, перебор фильтров не работает,
т.к не написан wrapper на функции с аргументом типа указатель-указатель.
Но в контексте скриптинга имеет место быть т.к:



Задачи


Перед тем как начать делать задачи, рекомендую сделать бэкап коллекции сцен,
с осторожностью использовать script_tick(вызывается раз в каждый кадр)
Проверять утечки памяти в папке logs, последняя строка последнего файла
пример время: Number of memory leaks: 0, если скрипт написан неправильно то
этой строчки там не окажется т.к OBS вылетит с ошибкой при закрытии.


3)[фильтры] "Динамическая прокрутка"
Создать программно или выбрать через интерфейс источник который будет фильтроваться,
к этом источнику добавить(если нет) фильтр Прокрутка (scroll_filter),
добавить интерфейс и/или горячие клавиши которые меняют значение вертикальной скорости
на случайную величину от 0 до 1000 при этом включать/выключать повторение с 50% шансом.


Гифка


4)[эвенты] "Проверка"
При переключении сцен проверять идёт ли запись.
Если нет вывести оповещение ( например через error())


5)[время и файлы] "Пост-продакшен"
Создать скрипт который при нажатии горячей клавиши записывает текущее время,
относительное время от старта записи, добавляет текст "МЕТКА",
а через интерфейс UI кнопку записать текст, и место для набора текста.
изображение


6)[предметы сцены] "Сумма"
Посчитать количество сцен и предметов сцен, записать ответ в названии первой сцены.
Не учитывать группы, т.к перебор предметов груп не работает.
Гифка


7) [фильтры и источники] "Нэйтив скриптинг"
Создать фильтр который будет с интервалом в 2 секунды включать и выключать источник за которым он закреплён.
Гифка


Ответы на задачи и код скриптов включая первую часть на Github


Ссылки


Подробнее..

Видео трансляция с OvenMediaEngine, до свидания nginx-rtmp-module

15.12.2020 04:09:34 | Автор: admin


Роман Арутюнян (rarutyunyan) выпустил модуль nginx-rtmp-module, это сильно перевернуло взгляд на доступность организации видеовещания. До этого, это казалось каким-то дорогим и сложным делом. 31 декабря Adobe официально хоронит флешплеер и убирает ссылки на скачивание с сайта. Это, конечно, не может не радовать. Эти засранцы то и дело подсовывали включенные по умолчанию галочки, так что пользователю прилетал вместе с флешплеером еще и антивирус mcafee в лучшем случае. То, что это чудовище бесконечно просило обновлений ручками через браузер, знают все. Ходил даже анекдот, предлагающий создателям флешплеера законодательно ограничить паспорта сроком на 1 неделю с возможностью бесконечной перевыдачи.

Кому сдался флешплеер в конце 2020-го, вы хотите сказать? Да дело в том, что флеш плеер единственный поддерживал воспроизведение протокола rtmp в браузере с относительно низкой задержкой. Да и он не так уж и плох, учитывая, что по умолчанию все стриминговые сервисы, youtube или twitch из кодировщика просят передавать им видео по протоколу rtmp. Конечно, приходит более свежий SRT но разговор не об этом. Вы убрали возможность играть видео в браузере по rtmp, а где альтернативы-то? Форматы, работающие по http требуют хорошей буферизации. Задержка выливается в 15 секунд. Это неприемлемо, если вы общаетесь со своей аудиторией онлайн. WebRTC решения плохо дружат с реализацией один ко многим. Ну как плохо, плати, и будет хорошо. Cофт есть на рынке. Только беда еще с покрытием, по моим ощущениям, WebRTC только только нащупал какую-то стабильную фазу, при которой его можно использовать. Но все равно есть небольшие проблемы с форматами видео на разных платформах. Раньше все это выглядело так муторно, что проще было просить ставить флешплеер только ради малой задержки.

В issue к nginx-rtmp-module не я один оставлял вопросы о поддержке форматов передачи видео по http с низкой задержкой (2-3 секунды). Ведь если бы можно было вещать в формате dash и hls до 3 секунд на nginx-rtmp-module, меня бы это полностью устроило. Но ответов на эти вопросы нет. Низкая задержка нужна в 2020 году и без нее ну никак. К сожалению, проект c 2017 года не развивается.

Медиасервер OvenMediaEngine.


Прекрасной альтернативой, отвечающей порывам всех моих желаний, является корейская морковка опенсорсный проект OvenMediaEngine, предлагающий не только средства кодирования и кластеризации (как у nginx-rtmp-module) но и средства воспроизведения т.е. свой html5 плеер. Именно то, чего я так искал, зарелизили наши южнокорейские братья. С большим интересом я крутил его неделю и полностью перебрался на него.

Задержка по WebRTC полсекунды. Задержка по dash low latency 2 секунды. HLS low latency скоро обещают.

Возможности:

  • RTMP Push, MPEG2-TS Push, RTSP Pull Input
  • WebRTC sub-second streaming
  • Embedded WebRTC Signalling Server (WebSocket based)
  • ICE (Interactive Connectivity Establishment)
  • DTLS (Datagram Transport Layer Security)
  • SRTP (Secure Real-time Transport Protocol)
  • ULPFEC (Forward Error Correction) with VP8, H.264
  • In-band FEC (Forward Error Correction) with Opus
  • Low-Latency MPEG-DASH streaming (Chunked CMAF)
  • Legacy HLS/MPEG-DASH streaming
  • Embedded Live Transcoder (VP8, H.264, Opus, AAC, Bypass)
  • Origin-Edge structure
  • Monitoring
  • Experiment
  • P2P Traffic Distribution
  • RTSP Pull, MPEG-TS Push Input

Так как команда активно развивает медиасервер, для быстрых апгрейдов я решил использовать предложенную ими установку через докер, накатывая внутрь контейнера всего две вещи: сертификаты от Lets Encrypt и файл настройки сервера.

С моей точки зрения из-за свежести проекта, документация OvenMediaEngine не рассказывает о best default practice да и пока еще пролетают огрехи копипасты. Вникая во все это самостоятельно, выделил две проблемы с подачей материала и почувствовал что нужна статья.

  1. Показывают, как работают примеры по http и ws протоколу, хотя, очевидно, показывать нужно сразу, как работать на https и wss, все равно же придется заново все перенастраивать. К тому же, о прикреплении бесплатных сертификатов от Lets Encrypt в документации ни слова, хотя официально полностью поддерживают.
  2. Аналогично, после настройки и запуска сервера точка входа публично доступна для всех.(как и у nginx-rtmp-module) Нужно сразу показывать, как защищать точку входа.

Это все мелочи. Похвалю за очень удобные средства отладки. Они предлагают две страницы

http://demo.ovenplayer.com
https://demo.ovenplayer.com

http и https для отладки сервера. Более того, внесенные настройки сразу же отражаются как GET параметры в адресной строке это чертовски удобно тестировать между браузерами. Поверьте, путаница в протоколах, портах, описках в урлах при первой подготовке сервера то еще занятие!А так, сохранил ссылку в браузере и возвращайся когда нужно к настройке с сохраненными настройками!

Установка. Быстрый старт


Итак, я возьму 20-ую Убунту.

https://airensoft.gitbook.io/ovenmediaengine/v/0.10.10/getting-started

docker run -d \-p 1935:1935 -p 4000-4005:4000-4005/udp -p 3333:3333 -p 8080:8080 -p 9000:9000 -p 10000-10010:10000-10010/udp \airensoft/ovenmediaengine:latest


После ставим certbot. Привязывайте ip к домену, получайте сертификаты.

Далее, получаем имя контейнера докера, например, 87b8610034bc

sudo docker container ls


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

sudo docker cp 87b8610034bc:/opt/ovenmediaengine/bin/origin_conf/Server.xml ./Server.xml


Старый добрый xml. (Мода же на json все дела но благо это вообще не xml как в каком нибудь IIS, который, казалось бы, выступает какой то базой данных для миллиона кнопок в интерфейсе вебсервера.)

Выглядит конфиг так
https://github.com/AirenSoft/OvenMediaEngine/blob/master/misc/conf_examples/Server.xml

Раздел VirtualHost. Нам нужно задать имя сервера и указать пути к сертификатам внутри контейнера.
<Host>    <Names>        <Name>stream.***.ru</Name>    </Names>    <TLS>        <CertPath>/opt/ovenmediaengine/bin/cert.pem</CertPath>        <KeyPath>/opt/ovenmediaengine/bin/privkey.pem</KeyPath>        <ChainCertPath>/opt/ovenmediaengine/bin/chain.pem</ChainCertPath>    </TLS></Host>


Затем, нужно оставить только TLSPort порты.
<Publishers>    <HLS>        <TLSPort>${env:OME_HLS_STREAM_PORT:8080}</TLSPort>    </HLS>    <DASH>        <TLSPort>${env:OME_DASH_STREAM_PORT:8080}</TLSPort>    </DASH>    <WebRTC>        <Signalling>            <TLSPort>${env:OME_SIGNALLING_PORT:3333}</TLSPort>        </Signalling>    </WebRTC></Publishers>

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

Заливаем конфиг обратно
sudo docker cp ./Server.xml 87b8610034bc:/opt/ovenmediaengine/bin/origin_conf/Server.xml

И, соответственно, по заданным путям мы кидаем наши ключи

docker cp /etc/letsencrypt/live/stream.****.ru/chain.pem 87b8610034bc:/opt/ovenmediaengine/bin/docker cp /etc/letsencrypt/live/stream.****.ru/privkey.pem 87b8610034bc:/opt/ovenmediaengine/bin/docker cp /etc/letsencrypt/live/stream.****.ru/cert.pem 87b8610034bc:/opt/ovenmediaengine/bin/


Перезапуск

sudo docker restart 87b8610034bc

Пробуем.

Урл вещания в obs
rtmp://stream.***.ru:1935/app


ключ stream

Линки для паблика

dash https://stream.***.ru:8080/app/stream/manifest.mpddash ll https://stream.***.ru:8080/app/stream/manifest_ll.mpdhls https://stream.***.ru:8080/app/stream/playlist.m3u8webrtc wss://stream.***.ru:3333/app/stream/


Если после запуска трансляции в obs все хорошо и по линкам отдается манифест, можете проверить видео на странице с плеером.

Подписывание ссылок


OME так устроен, что позволяет создать публичные линки с разными правами. Например, одну и туже ссылку можно ограничить ip диапазоном или временем работы по разному для разных людей. Они используют схожую логику как у гугла Sign Policy.

1. Добавить блок SignedPolicy в секцию VirtualHost в Server.xml

<SignedPolicy>    <PolicyQueryKeyName>policy</PolicyQueryKeyName>    <SignatureQueryKeyName>signature</SignatureQueryKeyName>    <SecretKey>secretkey</SecretKey>          <Enables>        <Providers>rtmp</Providers>        <Publishers>webrtc,hls,dash,lldash</Publishers>    </Enables></SignedPolicy>

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

2. Запускаем signed_policy_url_generator.sh с параметрами, описанными внутри.

Например:
sudo bash ./signed_policy_url_generator.sh secretkey rtmp://stream.***.ru:1935/app/stream signature policy '{url_expire:8807083098927}'

url_expire обязательный параметр, который просит в миллисекундах (это не unix timestamp, а currentmillis.com ) указать, когда истечет ссылка.

результат:

rtmp://stream.***.ru:1935/app/stream?policy=eyJ1cmxfZXhwaXJlIjo4ODA3MDgzMDk4OTI3fQ&signature=xjS7NY-l4lY1f9e9sOiRNhPtAqI


rtmp://stream.***.ru:1935/app идет в OBS в Server, остальная часть в Stream key.

3. Если OBS стартанул трансляцию, теперь нужно обязательно подписать необходимые публичные ссылки. Например для WebRTC.

sudo bash ./signed_policy_url_generator.sh secretkey wss://stream.***.ru:3333/app/stream signature policy '{"url_expire":8807083098927}'


Таким образом, не имея доступа к секрету, получить какой либо доступ к OME из дефолтных настроек больше нельзя.

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

sudo systemctl enable docker


sudo docker update --restart unless-stopped 87b8610034bc


О кодировании видео

Ребята считают OBS самым популярным кодировщиком для своего сервера. Поэтому как и в документации, так и более подробно в блоге можно найти подходящие настройки, максимально снижающие задержку в трансляции. Так же у них есть универсальный энкодер для андройда.
https://play.google.com/store/apps/details?id=com.airensoft.ovenstreamencoder.camera

Еще немного о корейской морковке


Когда пользователь выбирает в плеере в качестве источника webrtc, OME на лету конвертирует аудио в требуемый формат opus.(Это требования стандарта.)

По непонятным для меня причинам, WebRTC не может работать с mono звуком, поэтому не пытайтесь в настройках медиасервера переключать звук со стерео он не запустится. Это не проблема OME.

Пожелания



  1. Система логов это обычные txt файлики. Было бы очень круто иметь чуть более продвиную визуальную аналитику
  2. Я пробовал новый nginx-unit с его модным json-api в качестве команд управления/конфига. Суть в чем, обновляешь вебсервер, а он продолжает работать, заливаешь сертификаты, а ему не надо перезагружаться, домен, поддомен, добавить заголовки, убрать все налету без перезагрузки. А поверх json-api появляется миллион офигенно удобных админок с UI. Хотя в OME и вроде бы и нет нужды в таком API, но наверняка кто-то что-то потом обязательно придумает)


Немного о ребятах. Они себя позиционируют как группа экспертов по медиа технологиям, ведут блог с довольно полезным контентом.

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



Подробнее..

Перевод Жизнь инженера Netflix дело о лишних 40 мс

16.01.2021 14:23:21 | Автор: admin
Приложение Netflix работает на сотнях смарт-телевизоров, потоковых пультах и приставках платного ТВ. Инженер-партнёр помогает производителям устройств запустить приложение Netflix на их устройствах. В этой статье я расскажу об одной особенно сложной проблеме, которая заблокировала запуск устройства в Европе.




Как начались странности


Ближе к концу 2017 года я участвовал в конференции-связи, где обсуждали проблему с приложением Netflix на новой ТВ-приставке. Эта приставка была новым устройством Android с воспроизведением 4K на базе Android Open Source Project (AOSP) 5.0 Lollipop. В Netflix я имел дело с несколькими устройствами, но это было моё первое устройство Android TV.

В этой конференции участвовали все четыре игрока рынка: крупная европейская компания платного телевидения (оператор), эта компания запускала устройство; подрядчик, который интегрировал прошивку ТВ-приставки (интегратор); производитель микросхем; я представлял Netflix.

Интегратор и Netflix уже закончили строгую сертификацию Netflix, но во время внутреннего испытания оператора телеканалов один из руководителей компании рассказал о серьёзной проблеме: воспроизведение Netflix на его устройстве прерывалось, то есть видео проигрывалось совсем недолго, затем останавливалось, проигрывалось и снова прерывалось. Случалось это не всегда, но, как правило, спустя несколько дней после включения устройства. На представленной видеозаписи баг выглядел ужасно.

Интегратор нашёл способ воспроизвести проблему: нужно было несколько раз запустить Netflix, начать воспроизведение, затем вернуться в пользовательский интерфейс устройства. Нам дали сценарий, чтобы повторять ситуацию автоматически. Иногда воспроизведение ситуации с помощью скрипта занимало пять минут, но баг проявлялся всегда.

Тем временем полевой инженер производителя микросхем диагностировал причину проблемы: приложение Netflix, Ninja для Android-TV, медленно подавало аудиоданные. Видео останавливалось из-за истощения буфера в конвейере аудиоустройства. Ролик замирал, пока декодер ждал данных от Ninja. Когда новые данные поступали, проигрыватель оживал.

Интегратор, производитель микросхем и оператор решили, что проблема выявлена, их сообщение мне было ясным: Netflix, это ошибка в вашем приложении, исправьте её. В голосах я слышал напряжение. Выход ТВ-приставки на рынок запоздал, устройство превысило свой бюджет, и люди ждали результатов.

Расследование


Я был настроен скептически. То же самое приложение Ninja работает на миллионах устройств Android TV, включая смарт-ТВ и другие приставки. Если ошибка в Ninja, то почему она проявляется только на Android 5.0?

С помощью скрипта от интегратора я воспроизвёл проблему сам. Связался со своим коллегой у продавца микросхем, спросил, видел ли он что-то подобное раньше (он не видел). Затем я начал читать исходный код Ninja, потому что хотел найти фрагмент, который передавал данные. Я многое разузнал, но запутался в коде воспроизведения и нуждался в помощи.

Поднявшись наверх по лестнице, я нашёл инженера, который написал конвейер аудио и видео в Ninja, и он провёл экскурсию по коду для меня. Я посвятил какое-то время исходникам, чтобы разобраться в его рабочих частях; кроме того, чтобы закрепить своё понимание, я добавил собственное логирование. Приложение Netflix сложное, но в простейшем случае оно передаёт данные с сервера Netflix, буферизует несколько секунд видео- и аудиоданных на устройстве, а затем по одному доставляет кадры видео и сэмплы аудио на воспроизводящее оборудование.


Рисунок 1 Упрощённый конвейер воспроизведения

Давайте поговорим об аудио/видеоконвейере. Всё, вплоть до буфера декодера, одинаково на всех телевизионных приставках и смарт-ТВ, но перемещение аудио- и видеоданных в буфер декодера это процедура, которая зависит от устройства и работает в собственном потоке. Задача процедуры перемещения поддерживать заполненность буфера декодера через вызов API Netflix, этот вызов предоставляет следующий кадр аудио- или видеоданных.

В Ninja эта работа выполнялась с помощью Android Thread. Есть простой конечный автомат и логика для обработки разных состояний воспроизведения, но при нормальном воспроизведении поток копирует один кадр данных в API воспроизведения Android, а затем сообщает планировщику потоков, что он должен подождать 15 мс и снова вызвать обработчика. Когда вы создаёте поток Android, можно запросить, чтобы поток запускался повторно, как если бы в цикле; но это планировщик потоков Android и он вызывает обработчика, а не ваше собственное приложение.

Чтобы воспроизвести видео со скоростью 60 кадров в секунду (наивысшей чистотой кадров в Netflix), устройство должно отображать новый кадр каждые 16,66 мс, поэтому наличие нового сэмпла проверяется каждые 15 мс. Этого времени достаточно, чтобы опережать любой видеопоток Netflix.

Интегратор определил, что проблема кроется в аудиопотоке, поэтому я сосредоточился на конкретном обработчике потока, который доставлял аудиосэмплы в аудиосервис Android. Где же лишние миллисекунды?

Я предположил, что виновата какая-то вызванная обработчиком функция, поэтому прописал логирование по всему обработчику, предполагая, что код-виновник станет очевиден. Вскоре стало ясно, что в обработчике не было ничего плохого: даже когда воспроизведение прерывалось, он отрабатывал за несколько миллисекунд.

Прозрение


В конце концов я обратил внимание на три цифры: скорость передачи данных, время вызова обработчика и время, когда он передаёт управление обратно в Android. Я написал сценарий, чтобы проанализировать вывод логирования, и построил график, который ответил на мой вопрос.


Рисунок 2 Визуализация пропускной способности аудио и синхронизации обработчика потоков

Оранжевая линия показывает, как быстро данные перемещаются из буфера потоковой передачи в аудиосистему Android, в байтах за миллисекунду. На этой диаграмме можно увидеть три варианта поведения:

  1. Две высокие шипованные части, где скорость передачи данных достигает 500 байт/мс. Эта фаза буферизации, перед началом воспроизведения. Обработчик копирует данные так быстро, как только может.
  2. Область посередине это нормальное воспроизведение. Аудиоданные перемещаются со скоростью около 45 байт/мс.
  3. Область заикания находится справа, где аудиоданные движутся со скоростью ближе 10 байт/мс. Это недостаточно быстро, чтобы воспроизведение продолжалось.

Неизбежный вывод оранжевая линия подтверждает то, что рассказал инженер производителя микросхем: Ninja медленно передаёт данные. Чтобы понять причину, давайте посмотрим, о чём свидетельствуют жёлтые и серые линии. Жёлтая линия показывает время, проведённое в самой подпрограмме обработчика, это время рассчитывалось по записанным вверху и внизу обработчика отметкам.
И при нормальном воспроизведении, и при воспроизведении с заиканием время в обработчике было одинаковым: около 2 мс. Пики показывают случаи, когда выполнение замедлялось из-за затрат на другие задачи устройства.

Корень проблемы


Серая линия, время между вызовами обработчика, свидетельствует о другом. Когда видео проигрывается нормально, видно, что обработчик вызывается каждые 15 мс. Когда видео прерывается (справа), обработчик вызывается примерно каждые 55 мс. Между вызовами есть лишние 40 мс, а значит, успеть за воспроизведением невозможно. Но почему?

Я рассказал о своём открытии интегратору и производителю микросхем (посмотрите, виноват планировщик потоков Android!). Но они продолжали сопротивляться: почему бы вам просто не копировать новые данные, когда вызывается обработчик? Критика была справедливой, но, если переписать код таким образом, это повлечёт за собой больше изменений, чем я был готов внести, поэтому я решил продолжить поиск первопричины.

Я погрузился в исходный код Android и узнал, что потоки Android это конструкция пользовательского пространства, а планировщик потоков, чтобы определять время, использует системный вызов epoll(). Производительность epoll() не гарантируется, поэтому я подозревал, что на эту функцию влияет что-то системное.
И здесь меня спас другой инженер поставщика микросхем, который обнаружил ошибку; эту ошибку исправили в следующей версии Android Marshmallow. Планировщик потоков Android изменяет поведение потоков в зависимости от того, работает ли приложение в фоновом режиме или на переднем плане. Потокам в фоновом режиме задается дополнительное время ожидания в 40000000 нс. Ошибка в глубине самой Android означала, что дополнительное время возникает, когда поток перемещается на передний план.

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

Извлеченные уроки


Это была не последняя исправленная на этой платформе ошибка, но именно её было труднее всего отследить. Баг скрывался за пределами Netflix, не в конвейере воспроизведения; вместе с тем все исходные данные указывали на ошибку в приложении Netflix.

Эта история показывает одну из сторон моей любимой работы: я не могу предугадать все проблемы, которые наши партнёры перебросят мне, кроме того, я знаю, что для разрешения проблем мне нужно разбираться в нескольких системах, работать с замечательными коллегами и постоянно заставлять себя узнавать что-то новое. Моя работа прямо влияет на людей, на их удовольствие от отличного продукта. Я понимаю, что, когда люди наслаждаются Netflix в своей гостиной, именно я тот человек в команде, который делает это возможным.




Подробнее..

Музыканты и лейблы недовольны крупнейшим видеохостингом, но продолжают им пользоваться

28.02.2021 20:13:53 | Автор: admin

YouTube вновь отбивается от критики. В этот раз акцент сместился с качества рекомендаций на взаимодействие с музыкантами. Последние недовольны размером компенсаций за стримы, жалуются на монополизацию индустрии и критикуют все крупные платформы. Те, в свою очередь, перекладывают вину на YouTube и вместе с лейблами не торопятся что-либо менять.

Фотография: Leon Bublitz. Источник: Unsplash.comФотография: Leon Bublitz. Источник: Unsplash.com

Денег нет

Авторы и исполнители музыкальных произведений все чаще делятся личным опытом заработка и критикуют площадки за незначительные выплаты. В случае с The Flashbulb они составили 24 тысячи долларов за 7 млн прослушиваний. Это $0,003 за стрим на Spotify, причем большая часть суммы в итоге ушла на оборудование и запись партий с помощью сторонних музыкантов. Сопоставимые данные об этой площадке $0,0035-0,004 за прослушивание привел и RAC, лауреат премии Грэмми. Для сравнения девяти платформ ему хватило одного твита.

Как показывает пример этого музыканта, компенсация за миллион стримов на YouTube превышает поступления от Pandora и SoundCloud. Однако представители Британской ассоциации производителей фонограмм считают, что именно крупнейший видеохостинг сдерживает рост выплат музыкантам. По их мнению, Spotify платит в десять раз больше, а YouTube еще и способствует распространению бесплатного контента и мешает другим стриминговым сервисам повышать стоимость ежемесячных платежей для слушателей, а значит и распределять более существенные суммы между авторами треков. Вот что говорит эксперт: Стоимость подписки на музыкальные сервисы не меняется уже практически десять лет, а пока идет время инфляция делает свое дело. Еще на рынке присутствуют площадки вроде YouTube, где пользователи практически ничего и не платят, по сравнению с аудиторией Spotify.

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

Что в ответ

Общение с представителями платформ и профильных ассоциаций инициировал парламентский Комитет по вопросам цифровой среды, культуры, медиа и спорта [Digital Culture, Media and Sport Committee, DCMS] Соединенного Королевства. В рамках очередных слушаний менеджмент крупнейшего видеохостинга мира отверг обвинения в рекордно низком уровне выплат музыкантам по сравнению с компенсацией, которую предоставляют другие стриминговые платформы. Однако все-таки признал, что порядок расчетов стоит сделать прозрачнее.

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

Фотография: lucas Favre. Источник: Unsplash.comФотография: lucas Favre. Источник: Unsplash.com

Вероятнее всего, дело исключительно в экономическом интересе. Даже с учетом того, что кто-то пиратит стримы, выкладывает чужую музыку в открытый доступ и обходит систему трекинга Content ID за счет многочисленных ухищрений, YouTube уже выплачивает правообладателям огромные суммы. Только за 2020-й сервис перевел в счет авторов и лейблов около 12 млрд долларов, а к 2025-му его руководство планирует стать лидером по этому показателю среди всех игроков музыкальной индустрии, включая конкурентов по стримингу музыки.

Как это понимать

Стоит признать, что мало кто откажется от возможности моментального стриминга практически любой из существующих музыкальных композиций и захочет вернуться к покупке дисков [хотя в этом есть свои преимущества]. Платить по доллару за трек или по центу за стрим вариант, на который тоже готовы пойти далеко не все. Вариативная стоимость стриминга альбомов? Тогда о плейлистах можно будет просто забыть. Кажется, готовых предложений, которые могли бы положительным образом повлиять на выплаты музыкантам и устроить как лейблы, так и онлайн-платформы, пока не существует. Поэтому нам еще предстоит узнать, какими они будут.


Что еще почитать у нас в Мире Hi-Fi:


Подробнее..

Перевод Первый стример за двадцать лет до появления Twitch

31.05.2021 10:13:24 | Автор: admin

Мститель Зот (Zot the Avenger) находится в своём собственном мире. На экране мы видим длинноволосого 12-летнего парня, ведущего себя как дерзкий, слегка неуклюжий подросток. Образ дополняется надетой козырьком назад бейсболкой и мешковатой футболкой. Зот в размеренном ритме и атмосфере уверенности собирается рассказать нам о файтингах в своей программе Video Games and More. Игры проецируются на экран за его спиной, мы замечаем характерное размытие камеры, направленной на кинескопный телевизор. Когда он запускает Street Fighter II и начинает играть за Балрога, поступает первый звонок в эфир по громоздкому бежевому проводному телефону.

Это не ретро-стрим с Twitch и не YouTube-шоу о винтажном железе. Это передача с общественного телевидения начала 1990-х годов, выпускавшаяся в эфир аризонского канала Access Tucson почти за 20 лет до рождения Twitch.tv. [Прим. пер.: общественное телевидение (public-access television) обычно некоммерческие масс-медиа США, в которых широкая публика может создавать телевизионные программы для ограниченного вещания по специальным каналам кабельного телевидения.]

Ты покажешь код на Mortal Kombat?, спрашивает восхищённый мальчик на линии. Зот готов показать любой код для любой игровой системы. Он перестаёт играть и откидывается на спинку кресла. Ребята из аппаратной, выведите на экран компьютерную графику, говорит он, и на экране появляется чит на включение крови в Mortal Kombat для консоли Super Nintendo. В 1993 году эта игра вызвала огромную волну споров о крови и жестокости в видеоиграх. Но задолго до появления Google и даже широкополосного доступа невозмутимый Зот уже раздавал детям то, что им было нужно.

Мне нравится прозвище, которое мне дали люди: первый стример, рассказывает Зот, больше известный под именем Джей-Джей Стайлс. Когда мы созвонились с ним через Zoom, в Аризоне было два часа ночи; первый стример рассказал мне о первом задокументированном случае стриминга видеоигр. Зот поставил передо мной одно условие: прежде чем соглашаться давать интервью, он хотел меня узнать, и мы примерно час говорили о моём прошлом. Когда я сказал ему, что жил в Лос-Анджелесе, он сразу же начал рассказывать свои воспоминания о жизни на Венис-бич. Стайлс фанат этики киберпанка, технологий как великого уравнителя возможностей и важности ведения архивов. В настоящее время он сотрудничает с Internet Archive над подготовкой постоянного онлайн-хранилища для его серии передач.

Streams like teen spirit


Передача Video Games and More родилась в 1993 году, задолго до широкого распространения идеи Интернета как сети общего пользования. В первую очередь я надеялся, что начав Video Games and More, я мог сказать в эфире: привет, ребята, я поиграл в крутые игры, и мне кажется, другим они тоже могут понравиться, поэтому я расскажу вам о них, объясняет он.

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

Помню, что после первого курса по обращению с камерой я в тот же день поработал над четырьмя телешоу, которые шли одно за другим, вспоминает Стайлс. В десять лет у меня была к этому тяга, поэтому я начал работать с молодыми людьми, тинейджерами над передачами типа The Forbidden Zone и Spanked, над настоящим контентом в стиле поколения X. После года работы над чужими проектами, от религиозных программ до информационных шоу, Стайлс подхватил лихорадку Мира Уэйна. Что если объединить его любовь к ток-шоу в стиле Мира Уэйна с тем, чем он уже и так занимался: игрой в видеоигры с друзьями и болтовнёй о том, что ему нравится?

image

Самые первые два эпизода Video Games and More были созданы в кафе через дорогу от телестанции, где была прямая трансляция, которую могли пользоваться любые люди. Стайлс говорит, что они стали как бы приквелом к серии из 37 эпизодов. Кажется, это было примерно в конце 1993-го, потому что в то же время Buffalo Bills играли с Cowboys на Супербоул (он оказался почти прав Супербоул XXVII проводился 31 января 1993 года). Но когда мы впервые делали шоу в студии, то играли в EA Sports NHL '93 на Sega Genesis и Mortal Kombat Genesis, и я просто постоянно болтал. В качестве собеседника был выбран его друг Джейсон Кингман. Я работал над этой программой, редактировал её, и сказал ему: Слушай, мне нужен будет соведущий на шоу, потому что я не хочу заниматься этим в одиночку, вспоминает Стайлс. Это слишком большой стресс для 12-летнего ребёнка.

Благодаря своему возрасту Стайлс имел естественное понимание своей целевой аудитории: других детей. По его прикидкам, в то время его передачу в среднем смотрело примерно 50 людей. Когда я упомянул эпизод, в котором он сказал звонившему, что Game Boy отстойная консоль, Стайлс объяснил, что сказал это, потому что не мог играть в темноте без отдельного устройства с подсветкой и увеличивающим стеклом, которое работало от батареек. Это меня разочаровало вы же знаете, что у детей нет денег? Как мне постоянно находить для него батарейки?

image

В некоторых фрагментах передачи Стайлс присутствовал на экране в виде головы поверх игр, в которые он играл и которые записывал.

Стайлс рассказал и о том, как экономил на производстве шоу. Он придумал способ, позволяющий при помощи паяльника или дрели превращать обычную VHS-кассету в S-VHS-кассету, которая была чуть дороже и имела повышенное разрешение. Он даже подал заявку на минигрант от Access Tucson на бесплатные S-VHS-кассеты. Как только Стайлс накопил достаточно кассет для записи личных копий каждого из эпизодов, он начал выпускать повторы эфиров.

Обычно для эпизода он записывал на VHS-кассету, как играет в игру, а затем делал монтаж на оборудовании телестанции. Особенно он гордится логотипом Zot the Avenger, который сделал сам в Deluxe Paint на Amiga 2000. Я запрограммировал координаты x-y-z так, что происходил переворот в 3D, рассказывает он, и я почти ощущаю его гордость через экран. Я очень горжусь тем, чего добился в телестудии. Я не полагался ни на кого, кроме членов моей команды, и обычно они попадали в программу, потому что я любил всё контролировать и отдавал им указания прямо в эфире.

Мать Стайлса подтолкнула его к покупке компьютера Apple II на остатки денег, полученных им от рекламы для McDonald's, поэтому у него появилось то, чего не было у большинства детей. Я был одним из первых пользователей диалап-интернета через провайдера AZ Starnet, предоставлявшего в моём регионе неограниченный доступ. В те времена это было очень круто. Изучив HTML по компьютерным журналам, он создал свой первый веб-сайт и начал собирать онлайн чит-коды и прохождения. Другим детям приходилось ждать, пока журналы придут по почте или смотреть его шоу.


Пусть в Video Games and More и не было Twitch-чата, зато тролли могли звонить по телефону (с 27:14).

Сам формат шоу тоже родился благодаря стремлению Стайлса к новым технологиям. Он подписался на множество журналов, в том числе на Game Players, Electronic Gaming Monthly, Nintendo Power и Sega Visions. Мой мозг был заполнен видеоиграми, новостями и прорывными технологиями. Ещё задолго до большинства детей он точно знал, чего ждать Sega CD и 32x, знаменитого шлема виртуальной реальности для Sega. И в некоторых эпизодах наряду с рассказами об играх, которые ему понравились, и прохождениями в прямом эфире он также зачитывал новости о железе.

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

С большой силой Зоту пришла и большая ответственность у общественного телевидения были свои правила, хоть FCC и закрывала глаза на неприличия и сквернословие кабельного телевидения. Из-за взрослых игр наподобие Mortal Kombat видеоигры в 90-х были темой горячих обсуждений. Даже несмотря на то, что я был маленьким ребёнком, я оставался продюсером, говорит Стайлс. И мог нести ответственность за всё, что выводил в эфир. Он рассказал об ещё одном местном продюсере Лу Перфидио, провокаторе, называвшем себя Великий Сатана. Перфидио допускал мастурбацию и выполнение пирсинга на женских телах в прямом эфире, а также совершил самый тяжкий грех распивание спиртного на программе. Его шоу быстро выгнали с эфира.

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


В 1997 году история Video Games and More подошла к своему концу Стайлс стал студентом и начал изучать программирование, а также заинтересовался музыкой. В качестве своего оружия он выбрал бас-гитару, и сегодня он работает музыкальным продюсером. Для меня это не было чем-то важным. Мне не нужны были церемонии, говорит он. Он по-прежнему встречается со своим старым режиссёром Марком и они играют в пинбол, но за стриминговой культурой Джей-Джей особо не следит слишком занят созданием музыки, видео и графики.

Как бы мне ни хотелось, я больше слушаю местное радио. У меня есть программы-напоминалки для Twitch но у меня не всегда удаётся смотреть его вовремя.

image

Что они делают, когда не молятся о мире во всём мире? Они играют в видеоигры, говорит юный Мститель Зот о фотографии тибетских монахов.

Даже сегодня, или, может быть, в особенности сегодня Стайлс верит в мощь технологий, способных изменить мир. Всё дело в общении, и во многих смыслах стриминг является полной, тотальной заменой телевидению и радио. Он происходит не по запросу, тебе нужно ловить время, когда идёт трансляция. Очевидно, что когда Стайлс был Зотом, он относился к своей ответственности очень серьёзно и через свою работу вкладывал огромное количество энергии в любовь к играм. Сегодня Стайлс искренне верит, что использование технологий может способствовать улучшению общения, и что благодаря спортивной чести можно достичь мира во всём мире.

Очевидно, что передача Video Games and More была не просто шоу это был предшественник современного стриминга игр. Технологии и их доступность объединяли нас, вспоминает Стайлс о времени, когда он работал в Access Tucson. Никто из нас не был богат. Мы просто приходили туда и использовали для донесения своего посыла очень дорогое оборудование, которое в обычной ситуации оставалось бы для нас недоступным. И это было таким киберпанковым. Я полностью осознавал, что делал тогда. Чем больше силы даёшь ребёнку, тем более ответственным он будет. А стриминг это сила.
Подробнее..

Перевод Pulsar vs Kafka сравнение и мифы

26.03.2021 08:19:22 | Автор: admin


Pulsar или Kafka что лучше? Здесь мы обсудим плюсы и минусы, распространенные мифы и нетехнические критерии, чтобы найти лучший инструмент для ваших задач.


Обычно я рассказываю об Apache Kafka и ее экосистеме. О Pulsar за последние годы меня спрашивали только коммитеры и авторы Pulsar. Они задавали сложные технические вопросы, чтобы показать, что Kafka не идет ни в какое сравнение с Pulsar. На Reddit и подобных платформах разгораются яростные и очень субъективные споры на эту тему. Я поделюсь своей точкой зрения, основанной на многолетнем опыте работы со стриминговыми опенсорс-платформами.


Сравнение технологий нынче в моде: Kafka vs. Middleware, Event Streaming и API Platforms


Цель сравнения технологий помочь людям подобрать подходящее решение и архитектуру для своих потребностей. Универсального решения не существует. И это не дело вкуса. Просто для каждой задачи есть свой инструмент.


При этом такие сравнения почти всегда субъективны. Даже если автор не работает на вендора и представляется независимым консультантом, скорее всего, у него все равно есть любимчики, даже если он сам себе в этом не признается. Однако полезно посмотреть на инструменты с разных точек зрения. Поскольку Apache Pulsar сейчас обсуждают, я решил поделиться своим мнением и сравнить его с Kafka. Я работаю в Confluent, а мы лучшие эксперты по Apache Kafka и ее экосистеме. И все же я постараюсь быть максимально объективным и оперировать голыми фактами.


Опенсорс-фреймворки и коммерческие программы постоянно сравнивают. Я и сам делал такие сравнения в своем блоге и на других платформах, например InfoQ: Сравнение платформ интеграции, Выбор подходящего ESB для ваших потребностей, Kafka vs. ETL / ESB / MQ, Kafka vs. Mainframe и Apache Kafka и API Management / API Gateway. Просто заказчики хотели понять, какой инструмент поможет решить те или иные задачи.


Если говорить о сравнении Pulsar и Kafka, ситуация немного отличается.


Зачем сравнивать Pulsar и Kafka?


Реальные и потенциальные заказчики редко спрашивают о Pulsar. Хотя, если честно, в последние месяцы чуть чаще где-то на каждой 15-й или 20-й встрече. Потому что фичи и варианты использования у них частично совпадают. Хотя, по-моему, все дело в паре статей о том, что Pulsar якобы в чем-то лучше Kafka. В пользу противоположной точки зрения нет никаких фактов и очень мало материала.


Я не видел ни одной организации, которая бы всерьез задумывалась о Pulsar в продакшене, хотя по всему миру множество пользователей, которым нужна технология распределенной обработки сообщений, вроде Kafka или Pulsar. По-моему, те, кто рекомендует Pulsar, чего-то не договаривают.


Например, их главный пользователь Tencent, крупная китайская технологическая компания, которая при этом очень активно использует Kafka везде, кроме одного проекта, где пригодился Pulsar. Tencent обрабатывает с Kafka десять триллионов сообщений в день (только представьте: 10 000 000 000 000). Если посчитать, Tencent использует Kafka в тысячу раз активнее, чем Pulsar (10 трлн против десятков млрд). Tencent с удовольствием рассказывают о своем деплое Kafka: Как Tencent PCG использует Apache Kafka для обработки 10+ трлн сообщений в день.


Сравнение двух конкурирующих опенсорс-платформ


Apache Kafka и Apache Pulsar две замечательные конкурирующие технологии. Логично будет их сравнить.


У Apache Kafka и Apache Pulsar очень схожий набор функций. Советую оценить обе платформы на предмет доступных функций, зрелости, распространения на рынке, опенсорс-инструментов и проектов, обучающего материала, проведения митапов по регионам, видео, статей и так далее. Примеры вариантов использования в вашей отрасли помогут принять правильное решение.


Confluent уже писал сравнение Kafka vs. Pulsar vs. RabbitMQ: производительность, архитектура и функции. Я тоже поучаствовал. Значит, сравнение уже есть


О чем тогда эта статья?


Я хочу рассмотреть несколько мифов из споров на тему Kafka против Pulsar, которые регулярно возникают в блогах и на форумах. Затем я сравню их не только по техническим аспектам, потому что обычно никто не говорит о Pulsar с этой стороны.



Kafka vs Pulsar мифы


Мне попадалось несколько мифов. С некоторыми я согласен, другие можно легко развенчать фактами. Ваше мнение может отличаться от моего, это нормально. Я излагаю исключительно свою точку зрения.


Миф 1. У Pulsar есть характеристики, которых нет у Kafka.


Правда.


Если сравнивать Apache Kafka и Apache Pulsar, можно найти различия в многоуровневой архитектуре, очередях и мультитенантности.


Но!


У Kafka тоже есть уникальные особенности:


  • В два раза меньше серверов, которыми приходится управлять.
  • Данные сохраняются на диск только один раз.
  • Данные кэшируются в памяти только однажды.
  • Проверенный протокол репликации.
  • Производительность zero-copy.
  • Транзакции.
  • Встроенная обработка потока.
  • Долгосрочное хранилище.
  • В разработке: удаление ZooKeeper (KIP-500), чтобы использовать и деплоить Kafka было еще проще, чем Pulsar с его четырехкомпонентной архитектурой (Pulsar, ZooKeeper, BookKeeper и RocksDB), а еще чтобы повысить масштабируемость, устойчивость и т. д.
  • В разработке: многоуровневое хранилище (KIP-405), чтобы повысить эластичность и экономичность Kafka.

Спросите себя: можно ли сравнивать опенсорс-платформы или продукты и вендоров с комплексным предложением?


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


Например. Понадобилось несколько лет, чтобы реализовать и испытать в бою Kafka Streams в качестве нативного движка обработки потоков. Как это можно сравнивать с Pulsar Functions? Последнее позволяет добавлять определяемые пользователем функции (UDF) безо всякой связи с обработкой реальных потоков. Или это скорее похоже на Single Message Transformations (SMT), основную функцию Kafka Connect? Не сравнивайте круглое с квадратным и не забывайте учитывать зрелость. Чем критичнее функция, тем больше зрелости ей требуется.


Сообщество Kafka вкладывает невероятные усилия в работу над основным проектом и его экосистемой. Только в Confluent 200 инженеров занимаются исключительно проектом Kafka, дополнительными компонентами, коммерческими продуктами и предложениями SaaS в основных облачных провайдерах.


Миф 2. У Pulsar есть несколько крупных пользователей, например китайский Tencent.


Правда.


Но! Tencent использует Kafka активнее, чем Pulsar. Отдел выставления счетов, где используется Pulsar, это лишь малая часть Tencent, в то время как остальные используют Kafka. У них есть глобальная архитектура на основе Kafka, где больше тысячи брокеров сгруппированы в единый логический кластер.


Будьте осторожны с опенсорс-проектами. Проверяйте, какого успеха добились с ними обычные компании. Если эту технологию использует один технологический гигант, это еще не значит, что вам она тоже подойдет. Сколько компаний из Fortune 2000 могут похвастаться историями успеха с Pulsar?


Ищите примеры не только среди гигантов!


Примеры обычных компаний позволят лучше понять, как применяется тот или иной инструмент в реальном мире. Если это не истории успеха от самих вендоров. На сайте Kafka можно найти много примеров компаний. Более того, на конференциях Kafka Summit в Сан-Франциско, Нью-Йорке и Лондоне каждый год разные предприятия из разных отраслей делятся своими историями и кейсами. Это компании из Fortune 2000, предприятия среднего бизнеса и стартапы.


Приведу один пример про Kafka. Для репликации данных в реальном времени между отдельными кластерами Kafka существует много разных инструментов, включая MirrorMaker 1 (часть проекта Apache Kafka), MirrorMaker 2 (часть проекта Apache Kafka), Confluent Replicator (от Confluent, доступен только в рамках Confluent Platform и Confluent Cloud), uReplicator (опенсорс от Uber), Mirus (опенсорс от Salesforce), Brooklin (опенсорс от LinkedIn).


На практике разумно использовать только два варианта, если, конечно, вы не хотите обслуживать и улучшать код самостоятельно. Это MirrorMaker 2 (еще не вполне зрелая новинка, но отличный выбор для средне- и долгосрочной перспективы) и Confluent Replicator (проверенный на практике во многих критически важных для бизнеса деплоях, но платный). Остальные варианты тоже нормальные. Но кто обслуживает эти проекты? Кто разбирается с багами и проблемами безопасности? Кому звонить, если в продакшене что-то случилось? Одно дело деплоить критически важные системы в продакшене, другое оценивать и пробовать опенсорс-проект.


Миф 3. Pulsar предлагает очереди и стриминг в одном решении.


Частично.


Очереди используются для обмена сообщениями между двумя точками. Они предоставляют асинхронный протокол взаимодействия, то есть отправитель и получатель сообщения не должны обращаться к очереди одновременно.


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


  1. Pulsar предлагает ограниченную поддержку очередей сообщений, потому что ему не хватает таких популярных функций, как XA-транзакции, маршрутизация, фильтрация сообщений и т. д. Это обычные функции в таких системах сообщений, как IBM MQ, RabbitMQ, и ActiveMQ. Адаптеры Pulsar для систем сообщений тоже ограничены в этом смысле. В теории все выглядит нормально, но на практике...


  2. Pulsar предлагает ограниченную поддержку стриминга. Например, на практике в большинстве случаев он не поддерживает семантику строго однократной (exactly-once) доставки и обработки. Вряд ли кто-то станет использовать Pulsar для платежной системы, потому что платежи могут дублироваться и теряться. Ему не хватает функционала для обработки потоков с соединением, агрегированием, окнами, отказоустойчивым управлением состоянием и обработкой на основе времени событий. Топики в Pulsar отличаются от топиков в Kafka в худшую сторону из-за BookKeeper, который был придуман в 2008 году как лог упреждающей записи для HDFS namenode в Hadoop в расчете на краткосрочное хранение.



Примечание. Адаптер Kafka для Pulsar тоже ограничен. В теории звучит заманчиво, но в реальности не все получается, потому что он поддерживает только небольшую часть функционала Kafka.


Как и Pulsar, Kafka предлагает ограниченную поддержку очереди.


В Kafka можно использовать разные обходные пути, чтобы реализовать нормальное поведение очереди. Если вы хотите использовать отдельные очереди вместо общих топиков Kafka для:


  • Безопасности => используйте Kafka ACL (и дополнительные инструменты, вроде контроля доступа на основе ролей (RBAC) от Confluent).
  • Семантики (отдельных приложений) => используйте группы консюмеров в Kafka.
  • Балансировки нагрузки => используйте партиции Kafka.

Обычно я спрашиваю заказчиков, зачем им нужны очереди. Kafka предлагает готовые решения для разных сценариев, на которые можно просто посмотреть с другой стороны. Редко встречаются случаи, когда действительно требуется высокая пропускная способность с очередями.


Зная обходные пути и ограничения Pulsar и Kafka в плане сообщений, давайте проясним: ни одна из платформ не предлагает решение для обмена сообщениями.


Если вам нужно именно оно, возьмите что-то вроде RabbitMQ или NATS.


Однозначного решения здесь нет. Многие наши заказчики заменяют имеющиеся системы сообщений, вроде IBM MQ, на Kafka (из соображений масштабируемости и затрат). Просто нужно знать имеющиеся варианты и их недостатки, все взвесить и подобрать решение, которое лучше всего подходит именно вам.


Миф 4. Pulsar предоставляет потоковую обработку.


Неправда.


Или, если по-честному, все зависит от того, что вы называете обработкой потоков. Это какая-то простейшая функция или прямо полноценная обработка?


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



Pulsar предлагает минимальную потоковую обработку через Pulsar Functions. Она подходит для простых обратных вызовов, но не сравнится с функционалом Kafka Streams или ksqlDB для создания стриминговых приложений со stateful-информацией, скользящими окнами и другими функциями. Варианты применения можно найти в разных отраслях. Например, на сайте Kafka Streams есть кейсы New York Times, Pinterest, Trivago, Zalando и других.


Для стриминга аналитики Pulsar обычно используется в сочетании с нормальной платформой обработки потоков, вроде Apache Spark или Apache Flink, но вам придется управлять дополнительным элементами распределенной архитектуры и разбираться в их сложном взаимодействии.


Миф 5. Pulsar предоставляет семантику exactly-once, как и Kafka.


Неправда.


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


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


Семантика Exactly-Once Semantics (EOS) доступна с версии Kafka 0.11, которая вышла три года назад, и используется во многих продакшен-деплоях. Kafka EOS поддерживает всю экосистему Kafka, включая Kafka Connect, Kafka Streams, ksqlDB и такие клиенты, как Java, C, C++, Go и Python. На конференции Kafka Summit было несколько выступлений, посвященных функционалу Kafka EOS, включая это превосходное и понятное введение со слайдами и видео.


Миф 6. У Pulsar производительность выше, чем у Kafka.


Неправда.


Я не поклонник разных бенчмарков производительности и пропускной способности. Обычно они субъективны и относятся к конкретной задаче независимо от того, кто их проводит вендор, независимый консультант или исследователь.


Например, GIGAOM опубликовали один бенчмарк, где сравнивается задержка и производительность в Kafka и Pulsar. Автор намеренно замедлил Kafka, настроив параметр flush.messages = 1, в результате которого каждый запрос вызывает fsync и Kafka синхронизируется с диском при каждом сообщении. В этом же бенчмарке консюмер Kafka отправляет подтверждение синхронно, а консюмер Pulsar асинхронно. Неудивительно, что Pulsar вышел явным победителем. Правда, автор забыл упомянуть или объяснить существенные отличия в конфигурации и измерениях. Давайте не будем путать теплое с мягким.


На самом деле архитектура Pulsar сильнее нагружает сеть (из-за брокера, который выступает как прокси перед серверами bookie BookKeeper) и требует в два раза больше пропускной способности (потому что BookKeeper записывает данные в лог упреждающей записи и в главный сегмент).


Confluent тоже делал бенчмарки. Только там сравнивалось сопоставимое. Неудивительно, что результаты получились другими. Но нужно ли вообще встревать в эти бои на бенчмарках между вендорами?


Оцените свои требования к производительности. Сделайте proof-of-concept с Kafka и Pulsar, если надо. Скорее всего, в 99% случаев обе платформы покажут приемлемую производительность для вашего сценария. Не доверяйте посторонним субъективным бенчмаркам! Ваш случай все равно уникален, и производительность это только один из аспектов.


Миф 7. Pulsar проще в использовании, чем Kafka.


Неправда.


Без дополнительных инструментов вам будет сложно и с Kafka, и с Pulsar.


У Kafka две распределенных системы: сама Kafka и Apache ZooKeeper.


Но! У Pulsar три распределенных системы, а еще хранилище: Pulsar, ZooKeeper и Apache BookKeeper. Как и Pulsar, BookKeeper использует ZooKeeper. Для некоторых задач хранения используется RocksDB. Это означает, что Pulsar гораздо сложнее понять и настроить по сравнению с Kafka. Кроме того, у Pulsar больше параметров конфигурации, чем у Kafka.


Kafka движется в противоположном направлении скоро ZooKeeper будет удален (см. KIP-500), так что останется всего одна распределенная система, которую нужно деплоить, обслуживать, масштабировать и мониторить:



ZooKeeper мешает масштабированию в Kafka и усложняет эксплуатацию. Но у Pulsar все еще хуже!


Одна из главных проблем моих заказчиков использование ZooKeeper в критически важных деплоях в большом масштабе. С нетерпением жду упрощения архитектуры Kafka, чтобы остались только брокеры. Кроме того, мы получим единую модель безопасности, потому что больше не придется отдельно настраивать безопасность для ZooKeeper. Это огромное преимущество, особенно для крупных организаций и отраслей со строгим регулированием. Ребята из комплаенса и ИБ скажут вам спасибо за упрощенную архитектуру.


Использование платформы связано НЕ только с архитектурой


У Kafka гораздо более подробная документация, огромное сообщество экспертов и большой набор поддерживающих инструментов, которые упрощают работу.


Кроме того, по Kafka есть много вариантов обучения онлайн-курсы, книги, митапы и конференции. К сожалению, у Pulsar с этим все плохо.


Миф 8. Архитектура с тремя уровнями лучше, чем с двумя.


Зависит от ситуации.


Лично я скептически отношусь к тому, что трехуровневую архитектуру Pulsar (брокеры Pulsar, ZooKeeper и BookKeeper) можно считать преимуществом для большинства проектов. Тут есть издержки.


Twitter рассказал, как отказался от BookKeeper + DistributedLog (DistributedLog похож на Pulsar по архитектуре и дизайну) около года назад, соблазнившись такими преимуществами одноуровневой архитектуры Kafka, как экономичность и улучшенная производительность, которых недоставало двухуровневой архитектуре с отдельным хранилищем.


Как и Pulsar, DistributedLog построен на BookKeeper и добавляет стриминговый функционал, схожий с Pulsar (например, уровень обработки существует отдельно от уровня хранилища). Изначально DistributedLog был отдельным проектом, но потом присоединился к BookKeeper, хотя сегодня им, похоже, мало кто занимается (всего пара коммитов за последний год). Среди основных причин перехода Twitter на Kafka называлась значительная экономия и повышение производительности, а также обширное сообщество и популярность Kafka. Вот какие выводы они сделали: Для одного консюмера экономия ресурсов составила 68%, а для нескольких целых 75%.


Преимущества трехуровневой архитектуры проявляются при создании масштабируемой инфраструктуры. При этом дополнительный уровень увеличивает нагрузку на сеть минимум на 33%, а данные, которые хранятся в брокерах Pulsar, приходится дополнительно кэшировать на обоих уровнях, чтобы добиться аналогичной производительности, а еще дважды записывать на диск, потому что формат хранения в Bookkeeper основан не на логе.


В облаке, где работает большинство деплоев Kafka, лучшим внешним хранилищем выступает не такая узкоспециализированная технология, как BookKeeper, а популярное и проверенное хранилище объектов, вроде AWS S3 и GCP GCS.


Tiered Storage в Confluent Platform на основе AWS S3, GCP GCS и им подобных, дает те же преимущества без дополнительного слоя BookKeeper, как у Pulsar, и без дополнительных затрат и задержек, связанных с передачей данных по сети. У Confluent ушло два года на то, чтобы выпустить GA-версию Tiered Storage for Kafka с круглосуточной поддержкой для самых критичных данных. Tiered Storage пока недоступно для опенсорсной версии Apache Kafka, но Confluent вместе с сообществом Kafka (включая крупные технологические компании, вроде Uber) работает над KIP-405, чтобы добавить Tiered Storage в Kafka с разными вариантами хранения.


У обеих архитектур есть плюсы и минусы. Лично мне кажется, что 95% проектов не нуждаются в сложной трехуровневой архитектуре. Она может пригодиться там, где требуется внешнее недорогое хранилище, но вам придется отвечать за круглосуточное соблюдение SLA, масштабируемость и пропускную способность. А еще за безопасность, управление, поддержку и интеграцию в вашу экосистему. Если вам действительно нужна трехуровневая архитектура, не стану вас останавливать.


Связанный миф: Pulsar лучше подходит для отстающих консюмеров благодаря уровню кэширования и хранения.


Неправда.


Основная проблема отстающих консюмеров в том, что они занимают page cache, то есть последние сообщения уже кэшированы. При чтении из предыдущих сегментов они заменяются, что снижает производительность консюмеров, читающих с начала лога.


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


Миф 9. Kafka масштабируется хуже, чем Pulsar.


Неправда.


Это один из главных аргументов сообщества Pulsar. Как я уже говорил, это всегда зависит от выбранного бенчмарка. Например, я видел тесты с эквивалентными вычислительными ресурсами, где на высокой пропускной способности у Kafka результат был гораздо лучше, чем у Pulsar. Вот один из таких бенчмарков:



В большинстве случаев масштабируемость не проблема. Kafka можно легко разогнать до нескольких гигабайтов в секунду, как в демонстрации Масштабирование Apache Kafka до 10+ ГБ в секунду в Confluent Cloud:



Честно говоря, этот вопрос должен волновать менее 1% пользователей. Если у вас требования, как у Netflix (петабайты в день) или LinkedIn (триллионы сообщений), есть смысл обсуждать самую подходящую архитектуру, железо и конфигурацию. Остальным можно не беспокоиться.


Связанный миф: сейчас в Kafka может храниться всего 500к партиций на кластер.


Правда.


Пока у Kafka не лучшая архитектура для масштабных деплоев с сотнями тысяч топиков и партиций.


Но! Pulsar тоже не резиновый. Просто у него другие лимиты.


Ограничения в Kafka связаны с Zookeeper. Когда Zookeeper удалят через KIP-500, верхняя граница уйдет вместе с ним.


Примечание: успех зависит от подходящего устройства архитектуры!

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


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


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


Связанный миф: Pulsar поддерживает практически неограниченное число партиций.


Неправда.


У BookKeeper существуют те же ограничения по одному файлу на ledger, что и у Kafka, но в одной партиции таких ledger несколько. Брокеры Pulsar объединяют партиции в группы, но на уровне хранения, в Bookkeeper, данные хранятся в сегментах, и на каждую партицию приходится много сегментов.


В Kafka метаданные для этих сегментов хранятся в Zookeeper, откуда и возникают эти ограничения по числу. Когда Kafka избавится от этой зависимости, границы возможного раздвинутся. С нетерпением жду реализации KIP-500. Подробности читайте в статье Apache Kafka справится сама: удаление зависимости от Apache ZooKeeper.


Связанный миф: потребности масштабирования в Kafka необходимо определять при создании топика.


Отчасти это правда.


Если требуется очень большой масштаб, в топиках Kafka можно сразу создать больше партиций, чем обычно требуется для этой задачи. (См. Потоки и таблицы в Apache Kafka: топики, партиции и хранение.) Или можно добавить партиции позже. Это не идеальное решение, но так уж устроены распределенные системы стриминга (которые, кстати, масштабируются лучше, чем традиционные системы обработки сообщений, вроде IBM MQ).


Оптимальные методы создания топиков и изменения их конфигурации уже тщательно продуманы за вас, так что не волнуйтесь.


Но! У топиков Pulsar есть то же ограничение!


Пропускная способность для записи зависит от числа партиций, назначенных топику Pulsar, точно так же, как это происходит в топике Kafka, поэтому там тоже придется создавать партиции с запасом. Дело в том, что в каждой партиции записывать можно только в один ledger за раз (а их может быть несколько). Увеличение числа партиций динамически влияет на порядок сообщений, как и в Kafka (порядок нарушается).


У Kafka и Pulsar с масштабированием все отлично. Этого будет более чем достаточно почти в любом сценарии.


Если вам нужен совсем заоблачный масштаб, лучше взять реализацию без ZooKeeper. Так что KIP-500 это самое ожидаемое изменение в Kafka, судя по сообществу и заказчикам Confluent.


Миф 10. В случае аппаратного сбоя Pulsar восстанавливается моментально, а Kafka приходится перегружать данные.


И да, и нет.


Если брокер Pulsar вырубится, ничего не страшного не будет, это правда, но, в отличие от брокера Kafka, он и не хранит данные, а просто выступает в качестве прокси для уровня хранения, то есть BookKeeper. Так что подобные заявления о Pulsar это просто маркетинговый ход. Почему никто не говорит, что бывает, если полетит нода BookKeeper (bookie)?


Если завершить и перезапустить BookKeeper bookie, данные будут точно так же перераспределяться, как и в Kafka. В этом суть распределенных систем с их репликацией и партициями.


Kafka уже предлагает эластичность.


Это важно. Основатель Confluent, Джей Крепс (Jay Kreps) недавно писал об этом: Эластичные кластеры Apache Kafka в Confluent Cloud. В облачном сервисе SaaS, вроде Confluent Cloud, конечный пользователь не думает об аппаратных сбоях. Он ожидает непрерывный аптайм и SLA на уровне 99,xx. С оплатой за потребление пользователь не заботится об управлении брокерами, изменении размеров нод, увеличении или уменьшении кластеров и подобных деталях.


Самоуправляемым кластерам Kafka нужны такие же возможности. Tiered Storage for Kafka это огромное хранилище, с которым данные не хранятся на брокере и восстановление после сбоев происходит почти моментально. Если добавить сюда такие инструменты, как Self-Balancing Kafka (эта фича от Confluent описана в статье по ссылке выше), можно вообще забыть об эластичности в самоуправляемых кластерах.


К сожалению, в Pulsar вы ничего подобного не найдете.


Миф 11. Pulsar справляется с репликацией между кластерами лучше, чем Kafka.


Неправда.


Любая распределенная система должна решать такие проблемы, как CAP-теорема и кворум в распределенных вычислениях. Кворум это минимальное число голосов, которое распределенная транзакция должна получить, чтобы выполнить операцию в распределенной системе. Такой подход позволяет обеспечить согласованность операций.


Задачи по кворуму Kafka поручает ZooKeeper. Даже после реализации KIP-500 и удаления ZooKeeper законы физики не перестанут действовать: проблемы задержки в распределенных системах существуют в таких регионах, как Восточная, Центральная и Западная часть США и даже по всему миру. Скорость света, конечно, впечатляет, но все же имеет ограничения.


Эту проблему можно обойти разными способами, включая использование инструментов репликации в реальном времени, например MirrorMaker 2 в Apache Kafka, Confluent Replicator или Confluent Multi-Region-Clusters. Эти варианты и советы см. в статье Архитектурные шаблоны для распределенных, гибридных, периферийных и глобальных деплоев Apache Kafka.



Вы не найдете универсальное решение, которое обеспечит глобальную репликацию + нулевой простой + нулевую потерю данных. Для самых критически важных приложений Confluent Multi-Region-Clusters предлагает RTO=0 и RPO=0 (нулевой простой и нулевую потерю данных) с автоматическим аварийным восстановлением и отработкой отказа, даже если упадет целый датацентр или облачный регион.


Для таких случаев архитектура Pulsar будет еще сложнее, чем ее базовая версия. Просто для георепликации Pulsar требует дополнительный глобальный кластер Zookeeper, а для больших расстояний это не годится. Обходной путь есть, но от CAP-теоремы и законов физики не уйдешь.


Что с Kafka, что с Pulsar вам нужна проверенная архитектура для борьбы с физикой в глобальных деплоях.


Миф 12. Pulsar совместим с интерфейсом и API Kafka.


Отчасти.


Pulsar предлагает простейшую реализацию с зачаточной совместимостью с протоколом Kafka v2.0.


У Pulsar есть конвертер для базовых элементов протокола Kafka.


В теории совместимость с Kafka выглядит убедительно, но вряд ли это серьезный аргумент для переноса действующей инфраструктуры Kafka в Pulsar. Зачем такой риск?


Мы слышали заявления о совместимости с Kafka и в других примерах, например для гораздо более зрелого сервиса Azure Event Hubs. Почитайте об ограничивающих факторах их Kafka API. Вы удивитесь. Никакой поддержки основных функций Kafka, вроде транзакций (и семантики exactly-once), сжатия или compaction для логов.


Раз, по сути, это не Kafka, существующие приложения Kafka будут вести себя непредсказуемо в таких вот совместимых системах, будь то Azure Event Hubs, Pulsar или другая оболочка.


Kafka vs. Pulsar комплексное сравнение


Выше мы говорили о мифах, которые гуляют по разным статьям и постам. С ними, вроде, все понятно.


Но я обещал, что мы поговорим не только о технических деталях. При выборе технологии важны и другие аспекты.


Рассмотрим три из них: доля на рынке, корпоративная поддержка и облачные предложения.


Доля на рынке у Apache Kafka и Apache Pulsar


Статистика в Google Trends за последние пять лет совпадает с моими личными наблюдениями интерес к Apache Kafka гораздо выше, чем к Apache Pulsar:



Примерно так же выглядит картинка сравнения на Stack Overflow и аналогичных платформах, по числу и размеру поддерживающих вендоров, открытой экосистеме (интеграция инструментов, обертки, вроде Spring Kafka) и подобным характеристикам.


Открытые вакансии еще один индикатор распространения технологии. Для Pulsar их мало, то есть его использует не так много компаний. Убедитесь сами поищите на любом сайте. Если искать по всему миру, для Pulsar вакансий меньше сотни, а для Kafka тысячи. Кроме того, в большинстве вакансий для Pulsar указано, что требуется опыт с Kafka, Pulsar, Kinesis и аналогичными технологиями.


В большинстве случаев такие характеристики важнее для успешного проекта, чем технические детали. В конце концов ваша цель решить определенную бизнес-задачу, правда же?


Раз Pulsar так мало распространен, почему о нем вообще говорят? Во-первых, потому, что независимые консультанты, аналитики и блоггеры (включая меня) должны рассказывать о новых современных технологиях, чтобы привлечь аудиторию. Если честно, люди любят об этом читать.


Корпоративная поддержка для Kafka и Pulsar


Корпоративная поддержка для Kafka и Pulsar существует.


Но все не совсем так, как можно ожидать. Вот несколько вендоров, к которым вы можете обратиться, если решили работать с Pulsar:


  • Streamlio (теперь принадлежит Splunk) компания, которая раньше стояла за Apache Pulsar. Splunk пока не объявили о своей будущей стратегии для поддержки пользователей, которые работают над проектами на основе Pulsar. Splunk славится своими популярными аналитическими платформами. Это их основной бизнес (1,8 млрд долларов в 2019 году). Единственное, на что жалуются пользователи, ценник. Splunk активно используют Kafka, а сейчас интегрируют Pulsar в Splunk Data Stream Processor (DSP). Сильно сомневаюсь, что Splunk вдруг увлечется опенсорсом, чтобы поддержать ваш драгоценный проект на базе Pulsar (возможно, чего-то можно ожидать от DSP). Будущее покажет.
  • StreamNative основана одним из изначальных разработчиков Apache Pulsar и поддерживает платформу стриминга на основе Pulsar. На июнь 2020 года у StreamNative было 13 (целых 13, да!) сотрудников в LinkedIn. Уж не знаю, хватит этого для поддержки вашего критически важного проекта или нет.
  • TIBCO объявили о поддержке Pulsar в декабре 2019 года. За последние годы стратегия у них сместилась с интеграции на аналитику. Пользователи их промежуточного ПО уходят от TIBCO толпами. В отчаянии они приняли стратегическое решение: поддерживать другие платформы, даже если у них нет никакого опыта и никакой связи с ними. Да, звучит как миф, но TIBCO делают то же самое для Kafka. Любопытный факт: TIBCO предлагает Kafka и ZooKeeper в Windows! Такого больше никто не делает. Все знают, это приводит к нестабильности и несогласованности. Но если что, TIBCO помогут вам с Kafka и Pulsar. Зачем вообще сравнивать эти платформы, если можно получить обе у одного вендора, причем даже на Windows, с .exe и bat-скриптами для запуска серверных компонентов:


Вендоров для Kafka больше с каждым днем.


Это очень распространенная на рынке платформа. Лучшее подтверждение поддержка от крупнейших вендоров. IBM, Oracle, Amazon, Microsoft и многие другие поддерживают Kafka и встраивают возможности интеграции с ней в свои продукты.


Окончательное подтверждение этому я получил на конференции Oracle OpenWorld 2019 в Сан-Франциско, где выступал менеджер по GoldenGate (великолепный и очень дорогой инструмент CDC от Oracle). В основном он рассказывал, как GoldenGate станет платформой интеграции данных вообще для всего. Половина выступления была посвящена стримингу, платформе Kafka и тому, что GoldenGate будет обеспечивать интеграцию с разными базами/озерами данных и Kafka в обоих направлениях.


Полностью управляемые облачные сервисы для Kafka и Pulsar


Какие облачные решения доступны для Kafka и Pulsar?


Для Apache Pulsar есть облачный сервис с очень говорящим названием:


Kafkaesque.


Я серьезно. Сами посмотрите [UPD: 17 июня они переименовали KAFKAESQUE в KESQUE. Видимо, поняли, всю комичность ситуации.]


Для Apache Kafka существуют разные предложения на выбор:


  • Confluent Cloud (SaaS) полностью управляемый сервис с оплатой по мере использования, круглосуточной доступностью, эластичностью и бессерверными функциями для Apache Kafka и связанной экосистемы (Schema Registry, коннекторы Kafka Connect и ksqlDB для обработки потоков).
  • Amazon MSK (PaaS) подготавливает ZooKeeper и брокеры Kafka, а конечные пользователи сами обслуживают их, исправляют баги, устанавливают обновления и т. д. Важный факт: AWS не включает проблемы с Kafka в поддержку и SLA 99,95.
  • Azure Event Hubs (SaaS) предоставляет конечную точку Kafka (с проприетарной реализацией) для взаимодействия с приложениями Kafka. Это легко масштабируемое решение с высокой производительностью. Это не вполне Kafka, просто эмуляция, и тут не хватает некоторых важных функций, вроде семантики exactly-once, compaction логов и сжатия. Не говоря уже о дополнительных возможностях, вроде Kafka Connect и Kafka Streams
  • Big Blue (IBM) и Big Red (Oracle) предлагают облачные решения для Kafka и соответствующих API. Не знаю, использует их кто-нибудь или нет. Понятия не имею, насколько они хороши, никогда не видел их в деле.
  • Много компаний поменьше, вроде Aiven, CloudKarafka, Instaclustr и других.

В общем, про распространенность Kafka и Pulsar на рынке все очевидно.


И все же Apache Kafka или Apache Pulsar?


В двух словах: Pulsar пока здорово отстает от Kafka по зрелости в плане надежности для больших масштабов и обширности сообщества.


И вообще не факт, что Pulsar лучше.


Есть смысл сравнивать их, если вы решили использовать только опенсорс-инструменты. Узнайте, что подойдет лучше именно вам. Не забудьте учесть технические характеристики, уровень зрелости, вендоров, сообщество разработчиков и другие важные факторы. Что вписывается в вашу ситуацию?


Если в Kafka и Pulsar есть не все нужные вам функции, выбирайте Kafka: для нее есть много вендоров и облачных решений. Pulsar, к сожалению, сильно отстает и вряд ли догонит в ближайшем будущем.

Подробнее..

Обсуждение почему индустрия подкастов все больше походит на стриминг сериалов и фильмов

11.11.2020 08:04:10 | Автор: admin

Со стримингом музыки и тем, как находить новые треки, когда рекомендательные системы плохо справляются со своими обязанностями, мы разобрались. Обсудим, как быть с подкастами.

 Фотография: Anne Nygrd. Источник: Unsplash.com Фотография: Anne Nygrd. Источник: Unsplash.com

Их стало так много, что не успеть не то что послушать, но и просто отследить выход новых записей, в том числе топовых передач. Масло в огонь подливают и стриминговые платформы, которые интегрируют все больше общедоступных программ в свои полузакрытые экосистемы.

К чему это нас приведет?

В чем дело

Весенний карантин смешал все звуковые карты подкастерам. Те, кто потирал руки в надежде на прирост аудитории, вложился в новые шоу временем и деньгами, были разочарованы.

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

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

Фотография: gotafli. Источник: Unsplash.comФотография: gotafli. Источник: Unsplash.com

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

Сделка на будущее

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

Некоторые программы и вовсе закрыли.

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

Майские сто миллионов, выложенные за эксклюзивные права на шоу Джо Рогана, подтвердили тренд: стриминговые платформы ставили на хедлайнеров, продолжая скупать все, что относится к подкастам от сервисов, автоматизирующих часть этого процесса, до крупнейших продюсеров, студий, а теперь и хостеров. Такая стратегия должна сгладить отток аудитории, предпочитающей стримить музыку с помощью одного приложения, а подкасты слушать в другом.

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

Новый фронт

Стриминговые войны начались всего несколько лет назад, но уже успели всем надоесть: зачастую зрителю предлагают уникальный контент и эксклюзив только для того, чтобы брать регулярную оплату за доступ ко всей онлайн-библиотеке площадки. Ждет ли нас именно такое будущее в сфере подкастинга, где похожие процессы только набирают обороты?

Фотография: Dodi Achmad. Источник: Unsplash.comФотография: Dodi Achmad. Источник: Unsplash.com

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


Дополнительное чтение в Мире Hi-Fi:


Подробнее..

Вендор-лок для подкастов к чему он приведет

16.11.2020 00:15:06 | Автор: admin

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

Фотография: Gabriele Diwald. Источник: Unsplash.comФотография: Gabriele Diwald. Источник: Unsplash.com

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

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

Осторожно, шоу разбирают

Формат подкастов стал мощной альтернативой для радиопередач благодаря открытой модели распространения контента. Выпускать свои программы может кто угодно для их дистрибуции достаточно простой RSS-обертки, она же используется и для агрегации различных подкастов.

Механизмом свободно пользуются разработчики приложений для прослушивания подкастов например, Марко Армент (Marco Arment), который представил Overcast для iOS в 2014 году. Кстати, в одно время с релизом он инвестировал 50 тыс. долларов в развитие студии по производству подкастов под названием Gimlet Media. [Ее выкупили за 230 млн в 2019-м.]

Фотография: Annie Spratt. Источник: Unsplash.comФотография: Annie Spratt. Источник: Unsplash.com

Открытый формат поддерживают и те, кто проектирует инструменты для авторов программ хостинги подкастов и feed-бернеры, позволяющие учитывать требования витрин [вроде Apple Podcasts] к формированию RSS-лент. С их помощью ведущие быстрее находят свою аудиторию, а она может легко подписываться на аудиопередачи и следить за новыми выпусками.

Но сделки по поглощению разработчиков таких продуктов крупными вендорами происходят все чаще. Вместе с Gimlet Media шведы в прошлом году купили и интегрировали в свою вертикаль сервис Anchor, задействовав весь его инструментарий. В свою очередь, SiriusXM летом приобрели похожий продукт Simplecast, а Apple забрала ScoutFM, специализирующийся на подкаст-рекомендациях.

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

Именно так сложилась судьба подкастинговой платформы Luminary, которую пытаются вытянуть по аналогии с Gimlet. В конце прошлого года туда даже пригласили топ-менеджера HBO Саймона Саттона (Simon Sutton). Но пока дела у компании идут скромно. Говорят, что с начала кризиса Luminary пришлось вывести за штат часть сотрудников, а некоторых сократить.

Фотография: ConvertKit. Источник: Unsplash.com Фотография: ConvertKit. Источник: Unsplash.com

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

Не в лучшей форме

Инвестиции и громкие сделки не всегда являются показателем прироста слушателей и интереса со стороны рекламодателей. Пока этому рынку еще только предстоит взять планку в миллиард долларов. [Прогноз для США, где один только падающий сегмент ТВ-рекламы в 70 раз превышает эту сумму.] Получится ли сделать рывок в контексте оттока аудитории к новостям и политическим программам большой вопрос. Сейчас у подкастов есть множество конкурентов, которые не собираются отступать. Это видеостримы и игровые трансляции. Как развивается эта борьба, и чего можно ждать обсудим в следующем материале.


P.S. Дополнительное чтение в Мире Hi-Fi:


Подробнее..

Плейлистификация захватила умы паблишеров музыки и подкастов, но так ли она интересна слушателям

20.12.2020 02:12:46 | Автор: admin

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

Фотография: Advantage Video Productions. Источник: Unsplash.comФотография: Advantage Video Productions. Источник: Unsplash.com

Что происходит

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

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

Такой подход позволяет исключить промежуточные звенья и вести дела напрямую с авторами, минуя посредников в области исключительных прав на записи и их распространение. Более того, как заявил глава одной из крупнейших стриминговых платформ, подкасты отвечают интересам аудитории и дают второе дыхание самой площадке: те, кто приходит слушать аналитические или развлекательные передачи часто переключаются на музыкальный контент. Работает и обратная механика, а инвесторы, глядя на рост базы подкастеров, активно вкладываются в акции компании.

Что все это значит

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

Фотография: NeONBRAND. Источник: Unsplash.comФотография: NeONBRAND. Источник: Unsplash.com

Решением, по мнению паблишеров, должны стать плейлисты, подобранные в зависимости от предпочтений и настроения пользователя сервиса.

Туда можно включать не только подкасты, но и рекламные интеграции например, нативные сегменты передач, где ведущие между делом обсуждают какой-либо продукт.

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

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


Заметки и дополнительное чтение в Мире Hi-Fi:


Подробнее..

Чего музыканты боятся больше пиратства или монополизации прав на результаты их творчества

22.12.2020 16:08:30 | Автор: admin

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

Фотография: Kelly Sikkema. Источник: Unsplash.comФотография: Kelly Sikkema. Источник: Unsplash.com

Вопрос на вопросе

Пиратство в оффлайне практически полностью истреблено. Сегодня сложно себе представить, как кто-то едет на рынок, чтобы бродить между палаток в поисках музыки. За этим по большей части идут в онлайн, а на фоне стриминга возня с подбором раздач и загрузкой рипов на устройства выглядит для многих просто невыносимой. Люди даже закрывают глаза на среднее качество выдачи рекомендательных систем и регулярно платят за доступ к облаку с музыкой.

Внимания и времени на так называемых пиратов просто-напросто не хватает.

Однако так было далеко не всегда. С запуска первого по-настоящему глобального стримингового сервиса прошло почти двадцать лет, и все эти годы СМИ регулярно сообщали, как лейблы закрывают файлообменники и торрент-трекеры один за другим.

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

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

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

Тут вы, наверное, скажете, что все это можно охарактеризовать простым совпадением.

Что-то пошло не совсем так

Есть мнение, что пока звукозаписывающие компании снимали сливки, празднуя хоть и частичное, но все-таки заметное снижение активности пиратов [на фоне роста спроса на стриминг], суммы, которые доходили до композиторов и исполнителей песен, не то чтобы не увеличивались, а с каждым годом снижались. И дело тут не в злом умысле или заговоре. Технологии просто снизили порог входа в индустрию: записывать треки и публиковаться стало как никогда легко, число музыкантов увеличилось, а внимание слушателей подорожало во всех отношениях.

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

Фотография: Dominik Vanyi. Источник: Unsplash.comФотография: Dominik Vanyi. Источник: Unsplash.com

Кажется, сейчас наступает определяющий момент. Пока владельцы сервисов пытаются через суд отбиться от необходимости платить больше авторам песен и защищают привычный для себя порядок расходов на контент и права на его онлайн-вещание, в борьбу вступают профсоюзы. Они подают петиции, называя текущую компенсацию в $0,003-$0,008 за стрим несоразмерной вкладу музыкантов в развитие самих платформ, где оседает большая часть их поклонников.

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

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

Доедая public domain

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

Взять хотя бы недавнюю настойчивую рекомендацию для игровых стримов на Твиче: Не ставьте чужие записи, если у вас нет на них прав. Иначе трансляцию могут заблокировать в автоматическом режиме по требованию правообладателей. Единственная альтернатива собственная музыкальная библиотека площадки, находящаяся в режиме бета-тестирования, и сторонние сервисы, где можно взять лицензии на треки для аудиопроектов и видео. Кстати, мы делали сразу несколько подборок с источниками такой музыки [по большей части бесплатной]:

Фотография: Omar Prestwich. Источник: Unsplash.comФотография: Omar Prestwich. Источник: Unsplash.com

Можем ли мы представить себе развитие событий, когда корпорации будут способны контролировать весь объем контента, являющегося в настоящий момент общественным достоянием? Решатся ли они сделать из него коммерческий продукт? Получится ли провести очередную кампанию по обучению слушателей, музыкантов и других контент-мейкеров, чтобы отбить желание выкладывать свое творчество в открытый доступ? Попытки издателей засудить некоммерческий Internet Archive говорят, что и такого будущего, к сожалению, нельзя исключать.

P.S. Кстати, проблема пиратства, похоже, возвращается. Кризис может подтолкнуть часть слушателей к отмене платных подписок. Но обратят ли на это внимание стриминговые платформы, где все еще наблюдается рост доходов за счет премиальной аудитории? Есть вероятность, что ответы этот и другие вопросы придется искать в самое ближайшее время.


Заметки и другие подборки материалов:


Подробнее..

Как провести онлайн митап и сколько это стоит

22.06.2020 08:06:00 | Автор: admin


Привет! Меня зовут Антон Матренин, я один из организаторов сообщества ArtFlutter. Сегодня мы поговорим об онлайн митапах, платформах для онлайн конференций, стриминговых сервисах и в конце покажу пример настройки собственного онлайн-события.

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


Поиск спикеров и PR


У нас большое комьюнити по Flutter на 700+ человек в телеграмме, поэтому самым эффективным вариантом поиска был прямой контакт с активными участниками группы. Стоит также позаботиться о резерве, потому что всегда есть место форс-мажору и нужно быть готовым поставить кого-то на место выбывшего спикера. Будет большим подспорьем, если у вас в команде организаторов есть такой человек. С одной стороны проще с поиском, с другой ты будешь в резерве, если что на следующий митап попадешь в основу не самый большой козырь на переговорах со спикером. Еще будет круто, если у вас есть возможность организовать символический подарок для спикеров, ведь получить что-то на память всегда приятно.

С пиаром в нашем случае нам помог GDG Kyiv-Center мы предоставили им подробное описание и спустя пару часов появилось событие ArtFlutter Meetup #1. Плюс ко всему прошлись по нескольким смежным телеграмм-каналам с ссылками на событие, разумеется с разрешения администраторов. Вышеперечисленные действия дали нам стабильно 50-60 человек онлайна. Для первого раза результат достаточно неплохой, но если у вас найдется пару интересных рецептов для повышения онлайна делитесь в комментариях!


Выбор формата


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

Определившись с прямым эфиром я попытался найти платный сервис для проведения митапов, вебинаров и онлайн конференций. Я ожидал от сервиса таких функций:

  1. интеграция с YouTube
  2. Q&A сессия
  3. настраиваемая страница спикера
  4. возможность подключения второго (резервного) хоста, на случай разрыва и непредвиденных ситуаций
  5. демонстрация экрана
  6. настраиваемая музыка во время перерывов
  7. нарезка финальной записи на несколько частей по каждому докладчику
  8. цена: не более 50$ за один сеанс

Проведя небольшое исследование, я выбрал три варианта: zoom.us, Livestorm, BigMarker.

zoom.us


Цена: $309.98, 500 посетителей, 2 хоста

Zoom был первым сервисом, который хотелось пощупать и применить в действии, поскольку он зарекомендовал себя как стабильный продукт с качественной связью и удобным интерфейсом. При покупке пакета Видео веб-семинар Zoom у вас появляется доступ к дополнительным функциям, такие как: Q&A сессии, интеграция эфира на стриминговые сервисы, удобная панель работы организатора.

Однако есть ряд ограничений: нельзя интерактивно управлять экранами ожидания, невозможно поставить музыку для сглаживания перерывов между докладчиками, высокая стоимость для двоих организаторов.


Livestorm


Цена: 218$, 350 посетителей, 1 хост


Очень высокая цена, учитывая, что в этом тарифном плане есть только один организатор и 350 посетителей. За эту цену вас еще и ограничивают по времени события, которое составляет всего 4 часа. Это вполне достаточно для митапа, но не подойдет для длинной конференции. Плюс ко всему есть много функций, которые бесполезны в нашем случае:


  • Email уведомления и приглашения
  • Embedded функции для лендингов
  • Платные вебинары
  • CRM интеграции
  • Аналитика

Хорошее all-in-one решение, но абсолютно не ложится в концепцию простого митапа для открытого сообщества, а скорее подходит большим компаниям.


BigMarker


Цена 189$, 500 посетителей, 2 хоста


Основные особенности BigMarker:


  • Проведение неограниченного количества вебинаров;
  • Демонстрация нескольких экранов;
  • Шейринг презентаций;
  • Оформление страниц спикера;
  • Запись конференций;
  • Q&A-сессия в режиме реального времени;
  • Интеграция с Youtube.

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

Все вышеперечисленные сервисы не предлагают единоразовое событие за фиксированную цену, а хотят заключить сделку на ежемесячных платежах. Так что если вы планируете проводить 1-2 митапа в месяц скорее всего вам они не подойдут.


Стриминговые сервисы

После неудач с платными платформами я решил использовать стриминговые сервисы напрямую, настроив всю инфраструктуру на своей стороне. На выбор у меня было 2 сервиса: Twitch и YouTube. Twitch как платформа для стриминга очень неплоха и позволяет привлечь больше зрителей, благодаря внутренней системе рекомендаций. С недавнего времени это не просто площадка для игровых стримов, а совокупность различных направлений, включая искусство, музыку, стримы по программированию и обычного общения. Не так давно на твиче проводилась конференция Flutter Week, было интересно посмотреть на организацию похожих ивентов от зарубежных коллег.

YouTube имеет более простую систему для онлайн вещания, однако после стрима можно легко нарезать видео по каждому докладу, которое будет доступно в течении нескольких часов.

Большинство стримеров используют Restream.io замечательная система для одновременного стриминга на большое количество сервисов, включая YouTube и Twitch.

Для первого раза решено было использовать только YouTube как наиболее простой и менее затратный по настройке вариант.


Настройка программы для вещания


После выбора платформы необходимо настроить программу для потокового вещания. Стандартом де-факто является Open Broadcaster Software (OBS). Настройка особого труда не составляет, есть полно ресурсов описывающие подробные шаги по настройке звука, битрейта, интеграции со стриминговыми сервисами.

В этой статье мы коснемся только звуковых дорожек, настройки сцен и переключении между сценами.


1) Настройка звуковых дорожек


Для простейшего митапа достаточно трех звуковых дорожек. Первая ваш микрофон, который используется только стримером и транслирует ваш голос зрителям. Вторая дорожка источник медиа, который представляет из себя подготовленный MP3 файл с музыкой, который включается во время перерывов, в начале и в конце стрима. Любая музыка должна быть свободна от авторских прав, иначе финальное видео удалят с видеохостинга и, возможно, заблокируют аккаунт. Третья дорожка используется для трансляции голоса спикера. По факту, третья дорожка использует звук вашей системы, поэтому заранее надо отключить все уведомления системы и всевозможные посторонние звуки.

При настройке важно учитывать, что с базовой конфигурацией вы не можете слышать звук вашей системы в наушниках, когда транслируете этот самый звук на стрим. Для этого надо создать Multi-Output Device, совместив при этом выход ваших наушников и выход звука на стрим.

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




2) Начальная сцена (StartScene)


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



Важно помнить, что микрофон и звук системы должны быть выключены, а источник медиа включен, иначе музыка будет накладываться на шумы из микрофона и невозможно будет заранее созвониться с докладчиком.


3) SpeakerOneScene и SpeakerTwoScene


После того, как зрители собрались на стриме можно использовать экран первого спикера. Этот экран очень простой и состоит из заранее подготовленной одной картинки. В будущем эта картинка будет использоваться как превью отдельного видео на YouTube.




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


4) ShareScene


Большую часть митапа вы будете находиться на сцене с демонстрацией вашего экрана. Для связи можно использовать все, что нравится: Skype, Google Meet, Zoom. Сюда также можно добавить надписи о докладе и спикере, картинки спонсоров и партнеров, фоновые заставки и прочее.



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

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


День митапа


Прежде всего необходимо подготовить инструкцию для стримера, потому что быть режиссером занятие непростое и без определенной подготовки можно быстро растеряться. Для себя я подготовил такую последовательность действий:

Обозначения:

Mic 1 звук микрофона

Mic 2 звук системы

+ включено
выключено

====

запустить стрим

выбран StartScene, Mic 1, Mic 2

проверить, что стрим запущен, музыка играет

ждем 5-10 минут...

позвонить спикеру

выбран SpeakerOneScene, + Mic 1, Mic 2

вступительная речь...

выбран ShareScene, Mic 1, + Mic 2

доклад...

выбран SpeakerOneScene, + Mic 1, Mic 2

объявить о перерыве...

выбран StartScene, Mic 1, Mic 2

ждем 5-10 минут...

позвонить спикеру

выбран SpeakerTwoScene, + Mic 1, Mic 2

представление спикера...

выбран ShareScene, Mic 1, + Mic 2

доклад...

выбран SpeakerTwoScene, + Mic 1, Mic 2

объявить об окончании...

выбран StartScene, Mic 1, Mic 2

Остановить стрим

Рекомендую назначить горячие клавиши на все операции и потренироваться с участниками митапа, чтобы каждый из вас понимал в какой момент времени что нужно делать.

После завершения трансляции видео сразу будет доступно на YouTube. Используя встроенный редактор можно сразу нарезать 2 видео и поставить их в обработку. Через несколько часов эти видео будут доступны на вашем канале.


Что получилось?




Каждый спикер, в качестве поощрения за потраченные усилия, получил небольшую коробочку с футболкой нашего сообщества и стикер пак с логотипами Dart & Flutter.


Фото



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

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


Если вам интересны подобные стримы по Flutter следите за анонсами в нашем Telegram-канале.

Мы планируем делать следующий митап с новыми спикерами и новыми актуальными докладами. Поэтому приглашаем заинтересованные компании стать спонсорами нашего события. У нас есть действительно интересные предложения для партнеров, включая аудиторию нашего канала для вакансий, где многие участники активно ищут работу. По всем вопросам пишите в телеграм: @matreninAnton, @vasilich6107или на почту.

Подробнее..

Как организовать качественное видеомикширование источников во время онлайн трансляций?

20.11.2020 12:14:59 | Автор: admin
Кто сегодня не слышал про вебинары реалии сегодняшнего дня. Вебинары уже лет пять назад начали стремительно набирать обороты, а уж сегодня так это массово используемый прием обучения, продаж, маркетинговых исследований, представлений и так далее. Организации знают, чтобы оставаться на рынке, нужно постоянно генерировать новый контент и светиться на рынке. Значит контент должен выходить на свет все более качественный, приятный глазу и слушателю, удерживая его фокус внимания на нужных вещах.



Поэтому одна встроенная камера в ноутбук и сама презентация уже никого не удивляет. Люди прибегают к использованию нескольких камер с качественной оптикой, возможностью приближения, различными углами съемки, выносными микрофонами и так далее. Больше источников аудио и видео сигналов, плюс дополнительные требования к видеообработке, свету, микшированию сигналов, а также онлайн стриминг сразу в сеть просто вынуждают компании предлагать рынку готовые устройства все в одном потоковые видеокоммутаторы.

Популярность веб-конференций и направления коммутирования сигналов


Потоковое или живое видео всегда интереснее записи. Здесь все по-настоящему, есть ведущий, есть зрители и трансляции в таком формате проходят буквально тет-а-тет, достигается практическое живое общение, вплоть до озвученных вопросов от участников и такие же ответы ведущих. Соответственно для создания приятного глазу и слуху видео-контента требуется уровень камеры и звука чуть выше, чем от привычных стандартных встроенных устройств.

Хорошо, если камера может выдавать сигнал по USB, тогда не потребуются карты видеозахвата, но если использовать несколько камер уже будут сложности. Та же история со звуком отдельный микрофон-петличка, значит на приемной стороне будет аудио-кабель. Можно сразу и в компьютер, если есть микрофонный вход. А если микрофонов несколько тогда дополнительный микшер.

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



Аппаратные устройства


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

Дополнительный сильный толчок за счет произошедшей ситуации во всем мире с начала 2020 года позволил компаниям перестроить подход используемого оборудования под новые нужды. Таким образом, появился некоторый новый сегмент рынка, объединивший функционал работы с живым видео, работой с цифровыми сигналами, одновременно интегрировав микширование аудио и видео, упаковав все это в одном устройстве, приукрасив возможностью потоковой трансляции, что стало привычным для большинства компаний на сегодняшний день.

Никто не спорит, что видеомикшеры были и раньше, но речь идет про микшеры с уклоном в бытовые, если их можно так сказать, сигналы. Так еще с добавлением функций стриминга.

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

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

Потоковые видеокоммутаторы


Первая компания, о которой пойдет речь, берет свое начала в стране восходящего солнца Японии, в 1972 году. Основное направление производство электронных музыкальных инструментов и программного обеспечения к ним. Богатая история компании, зарекомендовав себя среди музыкальной индустрии, с 2010-х годов расширяет сферу влияния в области видео сигналов, итогом чего являются как раз компактные потоковые видеомикшеры.

Roland Corporation предлагает широкую линейку оборудования видеомикшеров, которая успевает двигаться в ногу со временем, поддерживая стандарты 4К качества, однако в роли потоковых микшеров выступают лишь три модели на конец 2020 года.
Модель VR-1HD VR-4HD VR-50HD MK II
Краткое описание Вещательная студия формата подключил и работай. Полноценная студия стандарта HD в формате компактного устройства. Расширенная модель, вобравшая мощный функционал студийного микшера с возможностью потоковой трансляции.
Входные интерфейсы 3х HDMI 4х HDMI 4х HDMI, 4х SDI
Выходные интерфейсы MAIN: 1х HDMI;
MONITOR: 1х HDMI;
THRU connector: 1х HDMI (from HDMI 3rd);
USB: 1x USB (type B);
MAIN: 1x HDMI or
RGB/COMPONENT;
PREVIEW: 1x HDMI;
USB: 1x USB (type B);
2x SDI (PGM OUT, AUX OUT);
3x HDMI OUT (PGM OUT, AUX OUT, MULTI-VIEW OUT);
2x Analog RGB/HD-Component (PGM OUT, AUX OUT);
USB: 1x USB (type B);
Микрофонные входы 2 XLR/TRS 4 комбо-разъема XLR/TRS 6 комбо-разъемов XLR/TRS
Линейные входы 1 стереофонический RCA 1 стереофонический RCA + 1 стереофонический миниразъем 2 стереоджековых 1/4" + 2 стереофонических RCA
Дополнительные возможности Выход USB 3.0 для онлайн трансляции, захвата и выдачи аудио-сигналов Выход USB 3.0 для онлайн трансляции, захвата и выдачи аудио-сигналов Выход USB 3.0 для онлайн трансляции, захвата и выдачи аудио-сигналов
Стоимость РРЦ (конец 2020 года) 105'500 руб 224'800 руб 528'900 руб
Помимо основных характеристик, микшеры поддерживают различные функции в числе которых присутствует бесплатное программное обеспечение, позволяющее записывать видео и аудио сигналы по USB сразу на жесткий диск компьютера.



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



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

imageДалее, начиная с базовой модели, присутствует возможность создания готовых пресетов, вызывая которые во время эфира или подстраиваясь на ходу, можно объединять картинку в картинке, применять совмещение или разбиение экрана (split screen).


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

И самое главное, что здесь есть это встроенная возможность подключения и трансляции аудио-видеосигнала по USB 3.0 на компьютер, а далее на любые платформы. При этом, помимо извлечения эмбедированного (внедренного) аудио сигнала из видеоисточников HDMI, можно микшировать аудио сигнал с порта USB во время звонков по программному ВКС (Skype, Zoom, Teams и так далее). Разработчики не забыли интегрировать функцию Echo Cancelation для предотвращения возникновения обратной связи с компьютерным аудио.



В более старшей модели VR-4HD видимыми различиями является встроенный сенсорный экран, на котором можно выводить multiview режим, а также информацию меню управления.

Есть поддержка функции DSK (Downstream Key) для накладывания титров, текстов песен или логотипов на видеосигналы источников, которые могут меняться.

imageА в расширенной модели VR-50HD MK II уже есть удаленное управление подключенными PTZ камерами, позволяя управлять шестью PTZ камерами одновременно по сети. Выходных интерфейсов три Program, Multiview, а также AUX, позволяя перенаправлять любой подключенный сигнал на данный выход, который работает независимо от основного программного выхода.

Итогом получаем компактное устройство, которое с одной стороны позволяет коммутировать видео-источники, с другой обеспечивает простое управление аудио сигналами. При этом все управление рассчитано на одного оператора, не требуя наличия специализированных знаний.

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

Blackmagic предлагает три варианта видеомикшеров для создания многокамерного контента на вещательном уровне.



Вся линейка микшеров лишена излишек, компактный дизайн, минимальные размеры, здесь учтено лишь только то, что нужно. Похоже на то, что разрабатывалось это устройство именно как дополнение для веб-трансляций и не более.
Модель ATEM Mini ATEM Mini Pro ATEM Mini Pro ISO
Краткое описание Модель имеет 4хHDMI входа, выходы 1хHDMI и 1хUSB, а также 2х микрофонных входа. В дополнении к модели mini, модель Pro имеет возможности записи в H.264 на флеш-диски USB, обеспечивать потоковую трансляцию через Ethernet. Имеется многооконный режим (до 4х источников). В дополнении к модели Pro, модель ISO позволяет вести запись до 5ти отдельных видеопотоков в H.264. Сохранять проектный файл DaVinci Resolve для дальнейшего монтажа.
Видео входы 4х HDMI 4х HDMI 4х HDMI
Видео выходы 1хHDMI
1xUSB
1хHDMI
1xUSB
1хHDMI
1xUSB
Разрешения Up to 1080p60 Up to 1080p60 Up to 1080p60
*support input standards up to 1080i/p60
**поддерживают автоматическое преобразование форматов на всех входах HDMI
Аудио входы 2х (mic) 3.5mm miniJack (stereo) 2х (mic) 3.5mm miniJack (stereo) 2х (mic) 3.5mm miniJack (stereo)
Multiview - + +
Стриминг С помощью бесплатного ПО Через Ethernet порт Через Ethernet порт
Запись на USB-флеш диски - + +
Стоимость РРЦ (конец 2020 года) 34'790 руб 59'900 руб 91'990 руб
Концепция данных устройств позиционируется именно как устройство для стриминга с функциями видеомикшера, поэтому здесь всего один выход HDMI, USB и LAN. В зависимости от модели, можно либо осуществить трансляцию через бесплатное ПО с компьютера через USB подключение (ATEM mini), либо непосредственно через Ethernet порт, а USB-интерфейс использовать для записи на USB-флеш накопитель (ATEM mini Pro и ISO).

imageВсе компактные микшеры данного производителя поддерживают эффектные переходы, возможность наложения титров, бесплатное программное обеспечение ATEM Software Control для удаленного управления с компьютера, плюсом имеется возможность разрабатывать собственные продукты с помощью пакета SDK.

Различия имеются лишь в потоковом вещании и записи сигналов для пост-обработки.

Базовая модель mini является мини-микшером с возможностью эффектного переключения 4-х входных сигналов и вывод любого из них через HMDI интерфейс. Если требуется стриминг тогда потребуется USB подключение к компьютеру с установленным ПО (бесплатным от производителя). А Ethernet порт в этой модели используется только для удаленного управления.

imageСредняя модель Pro имеет все характеристики базовой версии, но уже обладает возможностью стриминга непосредственно в H.264 через Ethernet порт. Порт HDMI в данном случае используется для режима multiview, на котором можно отобразить: сигналы preview, program, каждый входной сигнал, медиаплеер с выбранной графикой, состояние записи, трансляции и аудиоблока.

Получается, что для потокового вещания компьютер не нужен, а управление можно настроить хоть с телефона (ПО присутствует), подключив микшер и телефон к точке доступа wi-fi.

imageА расширенная модель Pro ISO позволяет производить запись пяти сигналов программного и чистых сигналов с входов для дальнейшего монтажа.


В итоге компания представляет три варианта, от самого простого, где требуется дополнительный ПК для трансляции, средний вариант который имеет уже полный функционал для микширования каналов, записи на внешние диски и главное, трансляцию. И топовый вариант для тех, кому больше необходима пост-обработка в дополнении к основному функционалу.


imageЕще одна компания, основанная в 1979 году в Тайвани, идущая с девизом просто лучшие соединения позиционируется на рынке как производитель коммутационного оборудования. В дополнении к уже существующему оборудованию, представила удивительно-компактный видеомикшер, чтобы не отставать от тенденций развития потокового контента на рынке.

ATEN UC9020 является микшером, у которого встроенного экрана нет. Поэтому, чтобы просматривать дополнительную информацию (а она нужна), придется приобрести планшет от не менее известной американской компании Apple. А чтобы планшет в неудобный момент времени не разрядился понадобится еще один разветвитель для питания.
Модель UС9020, UС-9020
Краткое описание Портативное устройства для микширование многоканального видео и звука с возможностью потоковой трансляции.
Видео входы 1x HDMI (до 4K@60Гц);
2x HDMI (до 1080@60Гц, переключаемые)
Видео выходы 1x Loop-Thru HDMI (до 4K@60Гц);
1 x HDMI (PGM) (до 1080@60Гц);
USB 3.0
HDCP Не поддерживается
Аудио входы Деэмбедирование из HDMI;
1x микрофонный вход, 6,5 мм (dual mono);
1x линейный вход, RCA
Аудио выходы Эмбедирование в HDMI;
1x разъем линейного выхода, 3,5 мм (стерео)
Запись на USB-флеш диски Через USB-порт
Стоимость РРЦ (конец 2020 года) 136'030 руб
Устройство без дополнительного планшета, выполняющего роль экрана, работать будет, но настроить будет невозможно. Микрофонный вход только один, хотя при этом присутствует захват 3х источников видео, один из которых поддерживает разрешение 4К и имеет свой проходной выход. Но максимальное выходное разрешение только fullHD.

Идеология устройства в том, что программное обеспечение, как и ПК не требуется, подразумевается работа в формате plug-n-roll. Заложенный функционал позволяет осуществлять предварительный просмотр и мониторинг через приложение на планшете, менять пресеты с выбором: полноэкранный режим, изображение рядом, картинка в картинке, позволяет накладывать текст и субтитры. Сама трансляция идет непосредственно через Ethernet порт, что удобно.

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

Еще один тайваньский производитель DataVideo, основанный в 1985 году, в основном специализирующийся на разработке и производстве оборудования для вещательного рынка, также выпустил микшерный пульт с возможностью потоковой трансляции в корпусе с основным 14 сенсорным экраном и дополнительными элементами управления.
Модель KMU-200
Краткое описание Устройство все в одном, позволяет переключать, микшировать звук, вести запись и потоковую трансляцию.
Видео входы 1x HDMI 2.0 (up to 3840x2160p@60);
1x HDMI 1.4 with Loop through (up to 1920x1080p@60)
Видео выходы 2x HDMI 1.4 (PGM, AUX) (up to 1920x1080p/i@60)
HDCP Не поддерживается
Аудио входы 2x XLR(Mic);
2x RCA
Аудио выходы 2x Unbalanced RCA
Запись на SD-карты Присутствует
Стоимость РРЦ (конец 2020 года) 359'325 руб

imageИтак, идеология устройства позволяет захватывать видео сигнал с двух физических интерфейсов, один из которых поддерживает 4K-разрешения, а другой (с доп. проходным выходом) только fullHD разрешения. При этом суть поддержки камер с разрешение 4K в том, чтобы можно было сделать 4 вырезки кадров из одного потока, тем самым получив 4 различных картинки (как будто у вас 4 входных видео потока).

Плюс остается общий вид и возможность подложить заранее подготовленную картинку. Итого шесть дорожек видео контента и шесть физических клавиш для переключения этих источников.

imageВидеомикшер позволяет как транслировать потоковый контент в H.264 по сети через Ethernet, так и записывать этот контент на SD-карту, разъем которого предусмотрен на лицевой части видеомикшера.

imageОсобенностью данного микшера является возможность съемки, обработки и трансляции видео контента не только в привычном landscape режиме, но и в портретном, что популярно для съемки или просмотра со смартфонов.

Соответственно, второй вход на микшере может использоваться для захвата презентационного материала с ПК. Два микрофонных входа с дополнительным входом интерфейсом RCA и таким же выходом. И в итоге получается достаточно интересный видеомикшер, который с одной стороны может вырезать 4 сцены из одного потока, второй вход с меньшим разрешением может использоваться для презентационного контента, захватывать звук с двух микрофонов и при этом поддерживать одновременный стриминг. Все это вместе создает компактное устройство.

Заключительный микшер, который уже достаточно давно продается на рынке, но не имеет такой популярности, как предыдущие. Разработан известной японской компанией, основанной в 1946 году представила еще в конце 2016 года микшер Sony MXC-500.
Модель MXC-500
Краткое описание Микшер с возможностями работы с различными камерами, использовать как 5-и канальный аудиомикшер. Стримить, вести запись на карты SD. И все это в удобном едином корпусе.
Видео входы 4x SDI;
2x HDMI (up to 1920х1080i/p);
Видео выходы 1x SDI (PGM);
2x HDMI (PGM, multiview) (1920x1080i/p);
HDCP Не поддерживается
Аудио входы Деэмбедирование из SDI, HDMI;
2x XLR/TRS;
Аудио выходы Эмбедирование в SDI, HDMI;
2x LINE L и R;
Запись на SD-карты Присутствует
Стоимость РРЦ (конец 2020 года) 220'000 руб
Видеомикшер позволяет вести микширование сразу нескольких входящих видеосигналов (до 4-х одновременных), есть несколько входных аудио-интерфейсов для подключения 2-х микрофонов, а также дэембедировать аудио сигнал из видео потока. Присутствуют возможности наложения титров, различные схемы наложения контента (например, PinP) и небольшое количество эффектных переходов. По выходам имеются два интерфейса: мультивью и программный выход.

А также встроенная запись на внешние SD-карты, заменяющая отдельный рекордер и одновременный стриминг в H.264. И все это в одном флаконе компактный мини-микшер.

Заключение


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

Видео-стриминг на iOS

10.05.2021 22:07:35 | Автор: admin

Интро

Недавно получил интересную задачу в работу, сделать приложение для видео-стриминга, это для стартапа ShopStory (ecomm live streaming). Первую версию приложения реализовал используя Open Source библиотеку для стриминга по RTMP HaishinKit. А вторую версию на Larix SDK. В этой статье разберу какие проблемы возникали в процессе.

О проекте

СервисShopStory.live- одна из первых в России B2B платформ для запуска продаж через live видеоэфиры на сайте e-commerce, которая сотрудничает с крупными ритейлерами, организуя стримы и предоставляя партнёрам удобные инструменты для привлечения новых покупателей и увеличения продаж. Платформа позволяет вести прямые эфиры на сайте клиента в удобном интерфейсе, что позволяет зрителям, находясь дома, быть ближе к товару, которые подробно презентует инфлюенсер. Клиентами ShopStory.liveстановятся известные бренды декоративной и уходовой косметики, маркетплейсы и небольшие компании, которые в основном представляют beauty-сегмент и хотят быть в тренде и использовать формат live commerce в своих маркетинговых стратегиях.

Требования

До разработки своего приложения в ShopStory, стримеры использовали LarixBroadcaster для проведения стримов, это бесплатное приложение для Android и iOS. Но такое решение имеет свои минусы:

  1. Для начала стрима, стримеру нужно зайти в админку, скопировать ссылку, а дальше в приложении LarixBroadcaster зайти в настройки соединений, и добавить эту ссылку. Стоит понимать, что стримеры это люди, которые не хотят лазить в настройки, предпочтительно нажать одну кнопку и стартовать стрим.

  2. Что бы смотреть чат, нужно рядом держать ноутбук, и с него читать что пишут зрители.

  3. Сложности с проведением тестовых эфиров.

  4. Куча настроек в приложении, в которых стримеру сложно и лень разбираться (битрейт, фпс, кодеки).

Что мы хотим от нашего приложения:

  • Видеть список запланированных стримов

  • Подготовка к проведению стрима (проверить камеру, микрофон)

  • ABR - Adaptive BitRate (при плохом соединении уметь снижать качество)

  • Готовые настройки битрейта, fps, энкодинга и т.п.

  • Простота для стримера при запуске.

В данной статье речь будет только про самую важную часть приложения стриминг. Larix SDK платный, поэтому сначала внедряем и используем бесплатную библиотеку.
Список бесплатных, которые рассматривали:

  • LFLiveKit 4.2k звезд на гитхабе, последний коммит в 2016г. 115 issue, которые не решаются.

  • HaishinKit 2.1k звезд на гитхабе, на момент написания последний коммит 7 мая. 11 issues.

  • VideoCore 1.5k звезд на гитхабе, последний коммит 2015г. Не поддерживается.

  • KSY Live iOS SDK 0.8k звезд на гитхабе, последний коммит 22 марта 2020. Весь README на китайском.

Остановились на внедрении HaishinKit. Если у вас есть на примете хорошие варианты, велком в комментарии, поделитесь какие там есть плюсы и минусы.

HaishinKit

Понятная документация, внедрение супер простое. Данная библиотека забирает на себя максимум. Разработчику не нужно заботиться о работе с камерой/микрофоном, эта либа делает всё за тебя. Никаких AVCaptureSession, AVCaptureDevice, AVCaptureDeviceInput и тому подобное. Просто создаем View, делаем attach к RTMPStream.

Накидаем протокол:

protocol BroadcastService: AnyObject {    func connect()    func publish()    func stop()}

Из документации берем примеры конфигурации и реализуем нужный нам класс.

class HaishinBroadcastService: BroadcastService {}

ABR - Adaptive BitRate

При хорошем соединении передает более высокое качество видео, когда интернет на телефоне начинает болеть, то понижаем качество (битрейт).

Для реализации ABR, берем пример из issue. Имплементим протокол RTMPStreamDelegate.

extension HaishinBroadcastService: RTMPStreamDelegate {    func rtmpStream(_ stream: RTMPStream, didPublishInsufficientBW connection: RTMPConnection) {        guard self.config.adaptiveBitrate else { return }        guard let bitrate = self.currentBitrate else {            assertionFailure()            return        }        let newBitrate = max(UInt32(Double(bitrate) * Constants.bitrateDown), Constants.minBitrate)        self.rtmpStream.videoSettings[.bitrate] = newBitrate    }    func rtmpStream(_ stream: RTMPStream, didPublishSufficientBW connection: RTMPConnection) {        guard self.config.adaptiveBitrate else { return }        guard let currentBitrate = self.currentBitrate,              currentBitrate < Constants.maxBitrate else {            return        }        guard self.bitrateRetryCounter >= Constants.retrySecBeforeUpBitrate else {            self.bitrateRetryCounter += 1            return        }        self.bitrateRetryCounter = 0        let newBitrate = min(Constants.maxBitrate, UInt32(Double(currentBitrate) * Constants.bitrateUp))        if newBitrate == currentBitrate { return }        self.rtmpStream.videoSettings[.bitrate] = newBitrate    }}private struct Constants {    static let bitrateDown: Double = 0.75    static let bitrateUp: Double = 1.15    static let retrySecBeforeUpBitrate = 20}

В отличии от варианта из issue опускаем битрейт постепенно (там просто сразу в 2 раза уменьшается), поднимаем тоже битрейт постепенно. Метод didPublishInsufficientBW вызывается в случаях, когда библиотека не может отправить все фреймы стрима.

Опытным путём остановились на таких константах:

  • если либа не может отправить все фреймы, мы снижаем битрейт умножая текущий на 0.75

  • если успешно отправились фреймы, то через 20 сек (эти методы делегата работают по таймеру в самой либе), пытаемся поднять битрейт умножая на 1.15

Live update resolution

Так же при падении качества соединения на телефоне стримера, сделали попытку изменения разрешения стрима, но это не увенчалось успехом. RTMP не поддерживает изменение разрешения на лету. Посмотрели как сделано в VK Live и там они разрывают соединение при изменении разрешения. В Instagram смогли это реализовать, вероятно есть разные rtmp ссылки, для разного качества и при снижении скорости интернета, начинается стрим в другую ссылку, а бэкенд уже это склеивает и обрабатывает (это лишь догадки, глубокого исследования не проводили). В ShopStory возможно реализуем позже.

Графики

После проведения ряда стримов периодически наблюдаем странные падения. Это происходит как на Wi-Fi, так и на LTE. Решили пробовать платное решение Larix SDK. Потому что при использовании LarixBroadcaster подобное не происходило.

Larix SDK

При покупке тебе предоставляют архив с исходниками LarixBroadcaster + LarixDemo (упрощенный вариант), общую диаграмму архитектуры и описание компонентов, StepByStepGuide.

Плюсы:

  • Широко используется в крупных компаниях, и в некотором роде стандарт для стриминга

  • Есть живая русскоговорящая тех. поддержка с экспертизой в стриминге

Минусы:

  • платное

  • документация очень скудная, если хочешь что-то сделать изучай код LarixBroadcaster (я люблю почитать исходники, но не в этом случае: over 2000 строк на файл)

  • нет дисконнекта когда теряется соединение с интернетом

  • нет отличий в connect и publish

Изучай код если хочешь что-то сделать

Оооо это отдельная боль, в LarixBroadcaster пришлось изучать ViewController на 2100 строк, и еще один важный класс Streamer на 1100 строк. Не ожидал я такого от платной SDK. Ок Для меня было загадкой, почему они не добавили это всё в кишки библиотеки. Получил комментарий от @Aquary (приглашаю в комментарии):

Изначально мы всю логику закрыли именно "в кишки библиотеки". Но жизнь оказалась разнообразнее нас постоянно просили добавить что-то ещё по мере выхода новых фич. Так что в итоге в библиотеке осталась часть, связанная с работой протоколов. Остальное исходники. Как показывает практика, клиентам такой подход ближе, т.к. нет почти никаких ограничений на реализацию со стороны нас, как разработчиков.

На мой взгляд могли бы, для этого дать из SDK понятный интерфейс и закрыть это всё протоколами для возможности расширения и своих кастомизаций. Здесь же бери исходники, вытаскивай нужное и тащи к себе в проект. Таким образом для переезда c HaishinKit нужно писать код для работы с камерой, микрофоном и т.д. (ранее это было всё скрыто в HaishinKit).

Такая же проблема и с ABR, я ожидал (ваши ожидания ваша проблема), что это будет встроено в либу, и просто задав один параметр можешь включить адаптивный битрейт. Но это не так. В LarixBroadcaster есть просто 3 класса StreamConditionerMode1, 2, 3, которые реализуют логику. Хочешь себе в проект ABR? Тащи еще к себе в проект эти классы или пиши свою реализацию ABR на основе этих исходников (это и плюс и минус).

Нет дисконнекта

Странно, но это так. Если на телефоне пропадёт соединение, то в метод делегата ты не получаешь status = disconnected. В обращении к тех поддержке ответили, что планируют это реализовать в ближайшее время.

func connectionStateDidChangeId(_ connectionID: Int32, state: ConnectionState, status: ConnectionStatus, info: [AnyHashable: Any]) {}

В Larix просто будет копиться буффер фреймов для отправки.
Решение: из класса SDK StreamerEngineProxy можем получить bytesSent и bytesDelivered, на основе этих двух методов, можно решать делать реконнект или нет. Если видим, что уже собирается большой буфер, то делаем принудительный дисконнект.

Connect и Publish

По спецификации RTMP, есть отдельные команды publish и connect, в Larix я не нашел (а может этого и нет), как отдельно вызывать эти команды. Из-за этого наш протокол BroadcastService теперь имеет изъяны.

Для чего нам такая возможность?

  • Что бы изначально можно было подключиться, посмотреть, что пакеты успешно отправляются без сбоев, возможно, настроить оптимальный битрейт, и только потом начинать стрим.

  • Для нормальной записи стрима. Всё, что записывается после вызова publish, попадет в конечную запись, и нужно будет вырезать, например, начало (подготовку стримера). Если делать publish только после того как стример готов (и поправил свою прическу). То постобработка не нужна.

Графики

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

Вывод

Выбор бесплатной библиотеки для стриминга на iOS не очень большой и по сути всё сводится к одному варианту HaishinKit. У него есть несомненное преимущество открытый исходный код и если с Larix не удастся выровнять графики и повысить стабильность, будем погружаться в open source и искать места, которые можно улучшать.

Покупая платную SDK не ожидай что она решит все твои проблемы, возможно у тебя их станет больше (изучать vc на over 2000 строк).

А какие-то более глобальные выводы можно будет сделать только после того, как обкатаем сборку на большем количестве стримов.

ShopStory.live активно развивается, расширяет сферу своей деятельности и планирует выполнять ещё больше задач в работе с клиентами. С каждым новым партнёром и очередным стримом платформа добавляет плюс к своей экспертности в live commerce. Именно поэтому платформа ShopStory.live ищет разработчиков! Если ты готов стать частью команды, и у тебя есть идеи, которые помогут сервису стать лучше, приглашает тебя к сотрудничеству!

Подробнее..

Как находить проблемы с интернетом и кто виноват ч.1

28.11.2020 00:23:46 | Автор: admin

Многие могут рассказать такую историю :
- Алло, техподдержка провайдера? У меня плохо открывается сайт aaaaaa.com.
- С нашей стороны пули вылетели, проблема в мишени у сайта - пишите туда.

- Привет. Это сайт aaaaaa.com? У меня плохо открывается ваш сайт.
- У нас всё хорошо, пишите провайдеру.

В этом цикле статей попытаемся разобраться - почему так происходит и собрать алгортим - как найти виновного, и что делать.


Disclaimer : автор знает, что

  1. Traceroute не всегда покажет проблемы, что маршруты больше про BGP и AS-PATH.

  2. Автор в курсе про пиринг, асимметрию, MPLS, BGP Communities и что килобайт это 1024 байта.

  3. Маршрут туда и обратно - два разных маршрута и traceroute разницы не покажет.

  4. Матерые сетевики могут найти очень много неточностей. Эти неточности допущены специально, для облегчения понимания материала не-сетевиками. :D

За чей счет банкет?

Интернет в России гораздо дешевле интернета, например в Америке или в Германии. Дешевле в несколько раз. Vodafone Kabel в Германии стоит 45 евро в месяц за 500 мегабит. Это 4000 рублей на момент написания текста. В России, например, у РосТелеком я плачу 1050 рублей в месяц за оптику, по которой приходит 600 мегабит.

Так как в России не производится коммутационное оборудование, то казалось бы - за чей счет банкет? Ведь железо стоит столько же сколько и в Германии. Попробуем в этом разобраться.

Путь от пользователя до сервера выглядит, обычно, следующим образом:

Городской роутер провайдера.

Я плачу 1050 рублей в месяц за 600 мегабит. На телеком-рынке стоимость 1 мегабита составляет от 6 до 30 рублей в зависимости от города. Это значит, что 600 мегабит интернета стоит от 3600 рублей. Как же мне РосТелеком продает всего за 1050? Этому есть несколько причин. Одна из ключевых он продает не только мне. Пользователь обычно не использует интернет на полную катушку 24х7. Поэтому, в тарифе написано - ДО 600 мегабит. С точки зрения математики это выглядит следующим образом:

В городском роутере есть 10 гигабит интернета. Этот интернет продали 500 пользователям. При этом, каждому продали по 1 гигабиту. И того продали 500 гигабит. А всего 10. Так как не все пользователи и не всегда качают фильмы с торрентов, то и проблем обычно нет.Это называется oversell.

Вечер пятницы.

В пятницу вечером проблемы, впрочем, могут начаться. В 17:00 школьники приходят домой с улицы, родители приходят домой с работы. Все садятся за компьютеры и начинают смотреть YouTube/Тикток и так далее. В этот момент как раз и получается, что 10 гигабит на город перестает хватать.

Для пользователя это выражается в следующем:

  1. Ухудшается пинг (иногда в несколько раз).

  2. Падает скорость.

Но, давайте будем честными при пинге до сайта в 4 мс и 20 мс, а также при скорости загрузки сайта в 50 мегабит и 600 мегабит, мы разницы, обычно, не чувствуем странички грузятся почти так же быстро, видео играется и, в целом, всё хорошо. Сайты нынче стали настолько требовательны к ресурсам компьютера, что важнее стала не скорость интернета, а производительность процессора и память.

Однако, если вы пользуетесь удаленным рабочим столом или ssh - разница ощущается. А в сервисах типа GFN.RU 4мс и 20мс input-лага это не только гораздо хуже картинка, но и разница между жизнью и смертью в Rainbow Six Siege.

Если со скоростью всё понятно, то на пинге стоит остановиться отдельно. Трафик в интернете движется со скоростью света. Независимо от загрузки магистрали, расстояние между пользователем и сайтом не поменялось почему же пинги стали хуже?

На сетевом оборудовании могут использоваться очереди (PBQ/QoS). Если пакет ушел в сеть, а канал загружен, то он может попасть в очередь и будет там болтаться либо пока не устареет, либо пока у него не появится возможность попасть в канал (пока не рассосется более приоритетный трафик).

В терминальных ситуациях, перегрузка канала выражается потерями пакетов при пингах. Это штатное поведение магистральных коммутаторов когда что-то не влазит, то что-то случайно отбрасывается до тех пор, пока не начнет влезать.

Тем не менее, не стоит беспокоиться TCP/IP (который используется при взаимодействии с сайтами) протокол с подтверждением доставки. Если что-то по пути потеряется, то потеря будет отправлена еще раз. Для пользователя это будет выглядеть как снижение скорости, которое он не заметит.

UDP (используется обычно для видео/голоса) более быстрый, но без контроля доставки, данные и правда могут потеряться по пути. Эти потери обслуживаются на более высоком уровне, по сравнению с TCP. В стриминговых сервисах потери UDP-пакетов приводят к снижению битрейта до тех пор, пока потери не прекратятся.

Стоит так же обратить внимание, что:

  1. Скорость у пользователя ДО 600 мегабит.

  2. Пинг в договоре не прописывается.

  3. Сайт может отдавать пользователю 20 мегабит вместо 600 даже при хорошей скорости от пользователя до сайта. Например, с помощью https://www.nginx.com/blog/dynamic-bandwidth-limits-nginx-plus-key-value-store/. И чтоб защититься от DDoS и краулинга.

  4. Для того, чтоб диагностировать скорость между сайтом и пользователем нужны специальные инструменты в том числе у сайта, и они должны быть доступны диагносту.

Вывод в обычной ситуации, доказать провайдеру, что между вами и сайтом проблема где-то у провайдера практически невозможно.

Маршруты в большом интернете.

После того, как трафик прошел городской роутер и дошел до магистрального роутера, он попадает в интернет.

 Топология интернета напоминает Mesh Сеть Топология интернета напоминает Mesh Сеть

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

BGP

Для выбора по какому маршруту отправить трафик, используется протокол BGP. С его помощью определяется количество узлов между двумя точками. Трафик может быть направлен по маршруту с меньшим количеством узлов (самый короткий AS-PATH). Однако, данный метод не учитывает такой метрики, как расстояние между узлами. Вполне может произойти, и происходит, что между двумя точками есть, например, два маршрута:

  1. AS123 <--1000km--> AS456 <--50км--> AS888

  2. AS123 <--5000км--> AS888

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

Загрузка канала и экономика.

Обратимся к первой картинке. Видим, что у провайдера есть 3 магистральных канала:

Оранжевый, синий и зеленый.

Синий самый жирный. Например, 8 гигабит. Оранжевый чуть менее жирный. Например, 4 гигабита. И зеленый самый тонкий: 2 гигабита.

При этом, синий самый короткий, оранжевый чуть длиннее и зеленый самый длинный.

Казалось бы - всегда используй жирный и короткий, не ходи тонкими и длинными. Но, в реальности, это происходит не всегда.

Канал между двумя точками всегда стоит денег. С точки зрения экономики это выглядит следующим образом:

  1. Арендуется оптическое волокно. В зависимости от ДЦ и жадности владельца оптики волокно стоит по-разному. Иногда, ОЧЕНЬ по-разному. Если на входе в ДЦ есть оптика только от одного владельца, которому, в том числе принадлежит ДЦ, то цена может быть сильно негуманной. Альтернатив-то нет.

  2. По этому волокну организовывается сетевая связь между двумя точками.

  3. Приобретается предоплаченная полоса трафика. Например, 3 гигабита.

  4. Договариваются о цене на Берсты: когда вместо оплаченных 3 гигабит по каким-то причинам наливается 5 гигабит. Обычно, берсты стоят дороже предоплаченной полосы и их стараются не использовать.

Берст (burst): кратковременное (или не кратковременное) превышение. В данном случае предоплаченной полосы. Провайдер в канале 10 гигабит купил всего 1 гигабит. Он может на самом деле использовать все десять. Всё, что выше купленого - называется берстом или превышением.

95 персентиль (95th percentile, MRTG95). Напоминает медиану (50th percentile). Как считается : берется отрезок времени, например 100 секунд. Разбивается на 100 отрезков по 1 секунде. В каждом отрезке определяется максимальная загрузка канала. Отбрасывается 5 отрезков с самой большой загрузкой. Из оставшихся отрезков находят отрезок с самой высокой загрузкой - это и будет 95 персентиль.

Нюанс с берстами. Загрузка канала считается по 95 персентилям. Это значит, что если в течение месяца канал более чем 32 часа загружен на 10 гигабит, даже если выкуплен 1 гигабит, и средняя загрузка 0.5 гигабит, то арендатору приходит счет за 10 гигабит. Поэтому, арендаторы стараются избегать берстов и загружать все свои каналы равномерно.

Всё вышесказанное напрямую влияет как именно ваш трафик пойдет от вас до сервера:

  1. Во-первых, по самому дешевому каналу.

  2. Во-вторых по тому, где есть неиспользованная предоплаченная полоса.

  3. В-третьих, если какой-то канал мигнул бёрстами, то их потом могут добивать: залил в какой-то резервный канал 10 гигабит в результате аварии на основном канале - значит, до конца месяца можно спокойно в резервный канал лить все 10 гигабит. Счет-то все равно уже придет за 10 гигабит.

  4. И уже на последнем месте будет учитываться скорость и комфорт пользователя.

Так же стоит отметить, что перегрузка магистрального канала на несколько процентов пользователями не чувствуется. Да, при перегрузке будут потери пакетов, но, как написано выше TCP и UDP трафик это спокойно обработает. TCP -на уровне протокола, а UDP на уровне приложения.

В интерактивных стриминг-сервисах, увы, это чувствуется инпут-лаг, рассыпающаяся картинка.

А еще, магистральное оборудование, может и не понимать, что бюджет канала исчерпан. Если маршруты говорят, что эти 12 гигабит стоит заливать в канал, в котором всего 10 гигабит полосы, то туда Nexus и попробует залить.

Всё вышесказанное говорит о том, что: когда вечером все начинают смотреть YouTube, то может как падать скорость, так и появляться потери пакетов. А трафик может ходить очень странными путями.

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

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru