Skip to content

Flussonic HTTP API

Содержание:

Общая информация по дизайну API

Мы (компания "Эрливидео") предоставляем клиентам разные продукты и сервисы, такие как Media Server, Watcher, Iris, Retroview и т.д.

На этой странице Вы найдёте актуальную информацию о принципах организации HTTP API к нашим системам.

Свойства API

Мы проектируем HTTP API для доступа других программ к нашим системам. Основные принципы, которые мы стараемся соблюдать:

  • ориентация на индустриальные стандарты и общепринятые практики с сохранением принципа разумности;
  • использование REST + JSON при построении API;
  • спецификация в формате OpenAPI 3.0 (бывший Swagger) для машинопригодного описания API;
  • удобство и простота создания как лёгких, так сложных запросов (например, простой запрос списка потоков и сложный запрос с несколькими фильтрами);
  • обеспечение единообразия терминологии между разными системами (имя сущности в одной системе должно быть одинаковым во всех системах);
  • обеспечение единообразия методов доступа к разным системам. На сервере может быть коллекция из одного бэкенда авторизации, а в сервисе хранения истории просмотров могут лежать триллионы записей о сессиях. Доступ к этим системам должен обеспечиваться единообразным API;
  • предпочтение HTTP вебсокетам. Доступ к данным по вебсокетам плохо стандартизован и трудно мониторится;
  • получение разумно ограниченного объёма данных по каждой выборке. Так клиент не будет получать огромное количество записей по умолчанию;
  • учёт работы с динамичным типом данных;
  • поддержка GET-запросов и задекларированных параметров в строке запроса (query string) для создания простых запросов доступа к большим коллекциям и отказ от сверхсложных правил парсинга строки запроса с переходом к JSON-языку запроса, передаваемому с помощью метода POST;
  • идемпотентность API, т.е. одинаковый результат при многократном повторе одних и тех же запросов;
  • обеспечение работы со сложными объектами, вложенными подобъектами и коллекциями.

Аутентификация и авторизация

Flussonic Media Server предоставляет возможность получать информацию и управлять определённой функциональностью при помощи HTTP.

Запросы на получение информации можно защитить с помощью директивы view_auth user password;, а на модификацию состояния Flussonic Media Server — с помощью директивы edit_auth user password; в конфигурационном файле /etc/flussonic/flussonic.conf.

Подробнее о настройке авторизации во Flussonic см. Авторизация.

Для доступа к HTTP API при настроенной авторизации необходимо указать логин и пароль в формате HTTP Basic Auth.

Так, например, для edit_auth user password; авторизация будет выглядеть следующим образом:

GET /flussonic/api/v3/streams HTTP/1.1
Host: FLUSSONIC-IP
Authorization: Basic dXNlcjpwYXNzd29yZA==

HTTP 200 OK
Date: Sun, 19 Sep 2021 19:40:22 GMT
Content-Type: application/json
...

Можно также использовать Bearer-авторизацию, используя тот же логин и пароль:

GET /flussonic/api/v3/streams HTTP/1.1
Host: FLUSSONIC-IP
Authorization: Bearer dXNlcjpwYXNzd29yZA==

HTTP 200 OK
Date: Sun, 19 Sep 2021 19:40:22 GMT
Content-Type: application/json
...

Note

Для других систем авторизация может отличаться, но чаще всего используется Bearer-авторизация с токенами.

Поддержка OpenAPI

Все системы, поддерживающие описанные в этом документе принципы, предоставляют описание сервисов в машиночитаемом формате OpenAPI 3.0. Этот формат является развитием таких форматов описания API, как Swagger и JSON Schema.

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

Эту OpenAPI-схему API медиасервера можно получить с работающего сервера Flussonic по следующему URL:

curl http://FLUSSONIC-IP:8080/flussonic/api/v3/schema

Ниже приведён пример того, как можно в несколько строчек кода с помощью React Query и openapi-client-axios получить доступ к списку потоков:

import React from 'react';
import { useQuery } from 'react-query'
import OpenAPIClientAxios from 'openapi-client-axios';


const api = new OpenAPIClientAxios({
  definition: 'http://localhost:8080/flussonic/api/v3/schema',
  axiosConfigDefaults: {
    headers: {
      'Authorization': 'Basic dXNlcjpwYXNzd29yZA==',
    },
  },  
});


function Streams() {
  const { isLoading, error, data } = useQuery({
    queryKey: "streams", 
    queryFn : () => {
      return api.init()
        .then(client => client.streams_list({}))
        .then(res => res.data);
    },
    keepPreviousData: true,
    refetchInterval: refetchInterval,
  });

  if(isLoading) return <div>Loading</div>;
  return <div>
    {data.streams.map((stream) => <div key={stream.name}>{stream.name}</div>}
  </div>;
}

Основная идея этого кода в том, что библиотека прочитает схему API, получит из неё список конечных точек, или эндпойнтов, и сгенерирует из них набор функций. В данном примере streams_list взят именно из схемы и сгенерирован программно.

Важно отметить, что OpenAPI не даёт возможности разделять приватное и публичное API.

Существует некоторое правило, касающееся приватного и публичного API: если у поля нет описания (description), то это часть приватного API. Таким образом, оно (поле) может поменяться без предупреждения и обратной совместимости.

Встроенный Swagger UI

Для удобства разработчика мы положили предсобранный Swagger UI:

http://FLUSSONIC-IP:8080/flu/swagger/index.html

Для начала работы с ним необходимо войти в интерфейс Администратора с помощью логина и пароля, чтобы Swagger смог воспользоваться авторизацией.

Выборка из коллекции

Практически все объекты организованы в коллекции (аналог SQL-таблиц). Сетевой доступ к системе на чтение данных во многом определяется способом чтения объектов из коллекции.

Для быстро работающих пользовательских интерфейсов и предсказуемо работающих программ необходимо:

  • уметь получать минимально необходимый набор данных,

  • иметь возможность достаточно надёжно получать все данные из коллекции.

Эти два требования немного конфликтуют друг с другом. Требование на ограничение набора данных подразумевает получение лишь части объектов из коллекции, например, 50 потоков из 2000, что есть на сервере.

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

Note

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

Для предсказуемого доступа к подмножеству коллекции мы описываем и реализуем язык, определяющий следующие действия над коллекцией:

  • фильтрация (аналог SQL WHERE),

  • сортировка (аналог SQL ORDER BY),

  • ограничение количества элементов (аналог SQL LIMIT),

  • дополнительная фильтрация по курсору (аналог SQL OFFSET),

  • ограничение количества полей (аналог SQL SELECT)

HTTP-методы доступа к коллекциям

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

Note

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

При использовании простого и даже примитивного языка строки запроса (query string) необходимо или использовать стандартный подход вида key=value, или использовать нестандартные разделители. В последнем случае такая строка запроса будет парситься нестандартно, что может вызвать ряд затруднений:

  1. Слишком сложные запросы при вложенных условиях. Написание такого рода условий в строке запроса (query string) будет выглядеть крайне громоздко и сложно, что противоречит одному из наших главных принципов — удобство и простота создания запросов.

  2. Неверная обработка запросов при использовании дополнительных разделителей в подмножествах. В таком случае необходимо помнить какие символы можно использовать без последствий, а какие — нет. Например, запятая (",") или дефис ("-") не используются в именах полей и не преобразуются в строке запроса. Таким образом, их можно использовать, в то время как амперсанд ("&") уже нельзя, т.к. это специальный символ для строки запроса и, если его не экранировать, то могут возникнуть проблемы при обработке запроса.

Так, например, некоторые компании используют в запросе сортировки символы - и + для указания направления сортировки. Символ + является спец. символом и при декодировании строки запроса будет расцениваться как пробел. Значит, необходимо либо экранировать его в %2B, либо воспользоваться нестандартным парсером, чтобы избежать возможных проблем с выполнением запроса. Использование нестандартных парсеров затрудняет подготовку запроса стандартными библиотеками.

Note

Существует ещё одна особенность, связанная с использованием символов Юникода (Unicode). У некоторых компаний аналог SQL запроса WHERE age > 20 кодируется в строке запроса (query string) как age>20. Использование Unicode-символа вместо стандартного ASCII-символа > позволяет избежать экранирования для размещения в HTML, но набрать такой запрос с клавиатуры весьма сложно. Мы, в свою очередь, отказались от использования символов Юникода, так что набрать из консоли их не удастся.

Описанные выше проблемы призваны проилюстрировать сложность упаковки разнообразных условий и аналогов языка SQL в очень ограниченный язык HTTP query string (язык строки запроса).

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

Формат ответа

При доступе к коллекции возвращается JSON-объект со следующими полями:

{
  "ITEMS": [...],
  "next": ...,
  "prev": ...,
  "estimated_count": ...,
  "timing": ...
}

Вместо поля ITEMS подставляется имя той коллекции, которую запрашивали. Для потоков это будет streams, для сессий — sessions.

  • next и prev — это значения курсоров (следующий и предыдущий соответственно).

  • estimated_count — примерное количество элементов в коллекции. Точность этого значения не уточняется.

  • timing — служебный объект с различными временами доступа. Не описывается, может измениться или удалиться.

Фильтрация коллекций

Чтобы отфильтровать запрос, добавьте параметры в URL строку запроса.

Запрос на фильтрацию по значению (provider) передается следующим образом:

curl http://FLUSSONIC-IP:8080/flussonic/api/streams?provider=Sky

Поддерживается запрос на вхождение в список:

provider=Sky,Canal,CNN (значения перечисляются через запятую)

Можно также указать условие на поле вложенного объекта:

stats.alive=true

Запросы не по прямому сравнению кодируются через суффиксы типа _lt. Так stats.delay_lt=5000 превратится в WHERE stats.delay < 5000.

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

Note

Так, например, в одном из вариантов API было принято решение передавать запросы не по прямому сравнению с помощью .: delay.lt=5000. Однако в этом случае авторы API лишились возможности давать доступ к полям вложенных объектов.

Ниже приведён список поддерживаемых суффиксов:

запись в строке запроса SQL
age_lt=50 age < 50
age_lte=50 age <= 50
age_gt=50 age > 50
age_gte=50 age >= 50
age_is=null age IS NULL
age_is_not=null age IS NOT NULL
age_like=pattern age LIKE 'pattern%'

Несколько указанных в query string фильтров применяются к коллекции последовательно, подобно запросам с использованием AND в SQL:

curl  http://FLUSSONIC-IP:8080/flussonic/api/v3/streams?stats.bitrate_gt=4000&stats.clients_count_lt=10

Note

Аналога OR для query string мы не предлагаем в силу сложной записи скобок.

Note

Поля фильтрации указаны без префикса. Например, можно было бы указывать их через filter.age=50. Это может быть удобнее с точки зрения программирования, валидации и т.п., но неудобно для человека, который будет пользоваться таким API.

Сортировка коллекций

Сортировка коллекций нужна для отображения в веб-интерфейсе Flussonic UI и получения предсказуемой постраничной выборки коллекции.

Параметры сортировки передаются через запятую к ключу:

sort=stats.ts_delay,-stats.bitrate

По умолчанию используется сортировка по возрастанию. Для смены направления укажите - перед названием поля.

Отсутствие префикса перед полями фильтрации означает, что мы не допускаем в нашем API поля sort в объектах.

Важно отметить, что в нашем API везде добавляется имплицитная сортировка. Если клиент закажет сортировку по полю provider (т.е. по полю, которое заведомо неуникально), то получится несколько групп объектов, которые отсортированы непонятным образом. Для этого мы дописываем в хвост запроса на сортировку поля типа name и position, применяя тем самым имплицитную сортировку.

Если они явно указаны в списке полей сортировки, то повторная сортировка по ним уже не производится.

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

Частичный доступ к коллекциям (курсоры)

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

Получить первые 100 элементов из коллекции очень просто: достаточно добавить поле limit=100 в строку запроса (query string). Вопрос в том, как получить следующиее 100 элементов.

Note

Классический ответ из баз данных SQL — передать поле offset. Однако мы от него отказались, поскольку он вычислительно дорогой (из-за алгоритма "маляра") и не имеет практической ценности. Мы говорили о том, что ряд коллекций может изменяться между соседними запросами, а значит, offset будет гарантированно промахиваться и отдавать все записи не последовательно, а неизвестно как, без шанса вычислить, что было потеряно.

Note

При постраничном доступе не требуется получать записи со смещением 100. Необходимо получить следующую пачку записей. Такой подход с курсорами совершенно непривычен для mysql, по причине их практического отсутствия в этой БД. Однако в более старых БД курсоры всё ещё используются.

В ответе на запрос первых 100 элементов мы отдаем поле next (а в следующих выборках и prev). Значение этого поля необходимо передать в качестве параметра cursor= в строке запроса и, таким образом, получить следующую выборку:

$ curl -sS "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams?select=name&limit=1&name_like=a&sort=name"  |jq 
{
  "estimated_count": 5,
  "next": "JTI0cG9zaXRpb25fZ3Q9MiZuYW1lX2d0PWEx",
  "prev": null,
  "streams": [
    {
      "effective": {
        "name": "a1",
        "position": 2,
        "section": "stream",
        "static": true
      },
      "name": "a1"
    }
  ],
  "timing": {
    "filter": 0,
    "limit": 0,
    "load": 3,
    "select": 0,
    "sort": 0
  }
}
$ curl -sS "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams?select=name&limit=1&name_like=a&sort=name&cursor=JTI0cG9zaXRpb25fZ3Q9MiZuYW1lX2d0PWEx"  |jq 
{
  "estimated_count": 5,
  "next": "JTI0cG9zaXRpb25fZ3Q9MyZuYW1lX2d0PWEy",
  "prev": "JTI0cG9zaXRpb25fbHQ9MyZuYW1lX2x0PWEyJiUyNHJldmVyc2VkPXRydWU=",
  "streams": [
    {
      "effective": {
        "name": "a2",
        "position": 3,
        "section": "stream",
        "static": true
      },
      "name": "a2"
    }
  ],
  "timing": {
    "filter": 0,
    "limit": 0,
    "load": 1,
    "select": 0,
    "sort": 0
  }
}

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

Ограничение возвращаемых полей

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

Для того, чтобы вернуть только часть полей, достаточно указать опцию: select=name,title. Также можно запросить поля вложенных объектов: select=name,stats.media_info.

Создание и обновление (upsert)

Традиционно концепция REST диктует разделение методов для создания и обновления уже созданных объектов.

Note

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

Note

Если на сервере и на клиенте не реализовать Idempotency token, т.е. уникальный идентификатор (ID) действия, то повторные запросы на создание могут приводить к созданию нескольких новых объектов. Клиент может и не знать об этом, потому что сетевые запросы могут прерываться и без получения ответа. В случае с теми данными, которыми мы оперируем, как правило, получается создать ID объекта на стороне клиента, а значит, не нужно запрашивать генерацию ID на сервере (как это бывает в случае с буквальным следованием REST).

Необходимо сделать PUT-запрос:

curl -X PUT -H "Content-Type: application/json" -d '{"title":"ORT"}' "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/ort"

Важный момент: для API очень удобно, чтобы ID объекта занимал один сегмент. Это означает, что, если, например, имя потока составлено из нескольких сегментов: sports/football, то в доступе через API необходимо экранировать символ / с использованием %2F следующим образом:

curl -X PUT -H "Content-Type: application/json" -d '{"key":"value"}' "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/sports%2Ffootball"

Такой подход мы называем UPSERT, потому что это аналог SQL UPSERT.

Update-протокол

В Media Server мы поддерживаем протокол обновления сложных вложенных объектов или даже списков объектов.

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

Традиционный ответ REST — сделать отдельную конечную точку (endpoint):

/flussonic/api/v3/streams/ort/inputs/4

Мы же предпочли проработать правила, по которым в передаваемом JSON можно закодировать команды на редактирование элементов вложенного списка.

Для начала надо отметить, что мы разделяем два типа вложенных списков: имеющих primary key и не имеющих. Например, источники потока не обладают первичным ключом, т.е. у них нет такого поля, которое обязано быть уникальным по природе данных. При этом программы в MPTS имеют уникальный первичный ключservice id.

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

В случае, если у вложенного списка есть первичный ключ, то этот ключ при редактировании используется в качестве идентификатора подобъектов. Если же у вложенного списка первичный ключ отсутствует, то будет использоваться специальное поле $index. Однако, если оно не было передано, то будет создан новый объект.

Пример:

$ curl -sS -d '{"inputs": [{"url": "udp://239.0.0.1:1234"}]}' -X PUT  "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/ort"  |jq 
{
  "name": "ort",
  "named_by": "config",
  "position": 7,
  "static": true,
  "inputs": [
    {
      "url": "udp://239.0.0.1:1234"
    }
  ]
}

Чтобы отредактировать существующий источник, используйте HTTP-метод PUT.

Пример:

$ curl -sS -d '{"inputs": [{"$index": 0, "$delete": true}]}' -X PUT  "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/ort"  |jq 
{
  "name": "ort",
  "named_by": "config",
  "position": 7,
  "static": true,
}

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

Пример:

$ curl -sS -d '{"inputs": [{"$index": 0, "$delete": true}]}' -X PUT  "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/ort"  |jq 
{
  "name": "ort",
  "named_by": "config",
  "position": 7,
  "static": true,
}

Чтение объекта

Прочитать объект можно с помощью простого HTTP-метода GET:

curl -sS "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/ort"  |jq

Ответ: JSON с информацией об объекте.

{
  "effective": {
    "name": "ort",
    "position": 7,
    "section": "stream",
    "static": true
  },
  "name": "ort",
  "named_by": "config",
  "position": 7,
  "static": true,
  "stats": {
    "alive": false,
    "bytes_in": 0,
    "bytes_out": 0,
    "client_count": 0,
    "dvr_enabled": false,
    "dvr_only": false,
    "dvr_replication_running": false,
    "id": "61496e6e-a22f-46af-bce5-5479f9067ead",
    "input_error_rate": 0,
    "last_access_at": 1632202350648,
    "lifetime": 0,
    "opened_at": 1632202350648,
    "out_bandwidth": 0,
    "publish_enabled": false,
    "remote": false,
    "retry_count": 19,
    "running": true,
    "running_transcoder": false,
    "start_running_at": 1632202350648,
    "transcoder_overloaded": false
  }
}

Удаление объектов

Удалить объект можно HTTP-методом DELETE:

curl -sS -X DELETE "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/ort"

Ответ: HTTP 204 без тела.

Работа с потоками в Media Server

Flussonic Media Server позволяет выполнять следующие манипуляции с потоками:

  • получение списка потоков:
curl -sS "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams" |jq

Ответ: JSON с информацией о списке потоков.

{
  "estimated_count": 13,
  "next": null,
  "prev": null,
  "streams": [
    {
      "inputs": [
        {
          "url": "fake://fake"
        }
      ],
      "name": "example_stream",
      "named_by": "config",
      "position": 0,
      "static": true,
      "stats": {
        "alive": true,
        "bitrate": 187,
        "bytes_in": 6105063537,
        "bytes_out": 0,
        "client_count": 0,
        "dvr_enabled": false,
        "dvr_only": false,
        "dvr_replication_running": false,
        "id": "6149e3a0-d8ec-4edf-8f92-463e85fa8ad2",
        "input_bitrate": 187,
        "input_error_rate": 0,
        "last_access_at": 1632232352867,
        "last_dts": 1632394204986.6667,
        "last_dts_at": 1632394205491,
        "lifetime": 161851626.66674805,
...
  • создание потока:
curl -X PUT -H "Content-Type: application/json" -d '{"inputs":[{"url":"fake://fake"}],"title":"Example"}' "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/STREAM_NAME" |jq

Ответ: JSON с информацией о созданном потоке.

{
  "inputs": [
    {
      "url": "fake://fake"
    }
  ],
  "name": "new_stream",
  "named_by": "config",
  "position": 14,
  "static": true,
  "stats": {
    "alive": true,
    "bitrate": 187,
    "bytes_in": 378985,
    "bytes_out": 0,
    "client_count": 0,
    "dvr_enabled": false,
    "dvr_only": false,
    "dvr_replication_running": false,
    "id": "614c627d-4f43-45a3-a11d-674bec71d59d",
    "input_bitrate": 187,
    "input_error_rate": 0,
    "last_access_at": 1632395901317,
    "last_dts": 1632395911986.6667,
    "last_dts_at": 1632395912497,
    "lifetime": 10666.666748046875,
    "media_info": {
      "title": "Example",
      "tracks": [
        {
          "bframes": 0,
          "bitrate": 161,
          "codec": "h264",
          "content": "video",
          "fps": 25,
          "gop_size": 25,
          "height": 240,
          "last_gop": 25,
          "level": "2.1",
          "pix_fmt": "yuv420p",
          "pixel_height": 240,
          "pixel_width": 320,
          "profile": "Baseline",
          "sar_height": 1,
          "sar_width": 1,
          "track_id": "v1",
          "width": 320
        },
        {
          "bitrate": 26,
          "channels": 2,
          "codec": "aac",
          "content": "audio",
          "lang": "eng",
          "sample_rate": 48000,
          "track_id": "a1"
        }
      ]
    },
    "opened_at": 1632395901317,
    "out_bandwidth": 0,
    "output_bitrate": 187,
    "publish_enabled": false,
    "remote": false,
    "retry_count": 0,
    "running": true,
    "running_transcoder": false,
    "source_id": "614c627d-5407-4419-b73b-69a25f4f010a",
    "start_running_at": 1632395901317,
    "transcoder_overloaded": false,
    "ts_delay": 583,
    "url": "fake://fake"
  },
  "title": "Example",
  "urls": [
    {
      "url": "fake://fake"
    }
  ]
}
  • получение информации о потоке:
curl -sS "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/STREAM_NAME" |jq

Ответ: JSON с информацией о запрашиваемом потоке.

{
  "chunk_duration": 300,
  "cmaf_enabled": true,
  "inputs": [
    {
      "url": "fake://fake"
    }
  ],
  "name": "example_stream",
  "named_by": "config",
  "position": 9,
  "static": true,
  "stats": {
    "alive": true,
    "bitrate": 187,
    "bytes_in": 6034345652,
    "bytes_out": 254192,
    "client_count": 0,
    "dvr_enabled": false,
    "dvr_only": false,
    "dvr_replication_running": false,
    "id": "6149e3a0-d8f0-4e84-a0c8-3349ae265f05",
    "input_bitrate": 189,
    "input_error_rate": 0,
    "input_media_info": {
      "tracks": [
        {
          "bframes": 0,
          "bitrate": 163,
          "codec": "h264",
          "content": "video",
          "fps": 25,
          "gop_size": 25,
  • удаление потока:
curl -sS -X DELETE "http://FLUSSONIC-IP:8080/flussonic/api/v3/streams/STREAM_NAME"

Ответ: пустой.

Важно обратить внимание на то, что запущенный поток — это объект, имеющий характеристики, изменяющиеся во времени. Т.е. в отличие от обычной базы данных SQL, в которой всё, что записали в таблицу, то и достали, у потока при чтении можно получить данные, отличные от тех, что были при записи. Например, поле runtime является вычисляемым в процессе работы потока, следовательно, его нельзя записать на сервер.