Skip to end of metadata
Go to start of metadata

Описание

Медиапоток, захваченный WCS, может быть записан при публикации.

Поддерживаемые протоколы:

  • WebRTC
  • RTMP
  • RTSP

Форматы записи:

  • MP4 для кодеков H.264 + AAC
  • WebM для кодека VP8 + Vorbis
  • TS для кодеков H.264 + ADTS

Краткое руководство по тестированию

Запись трансляции

1. Для теста используем демо-сервер demo.flashphoner.com и веб-приложение Stream Recording

https://demo.flashphoner.com/client2/examples/demo/streaming/stream_recording/recording.html


2. Нажмите кнопку "Start". Начнется захват и трансляция потока.


3. Нажмите кнопку "Stop". Трансляция остановится, отобразится ссылка на воспроизведение и скачивание записанного фрагмента


Настройка

Серверная часть

Включение и отключение записи потоков

По умолчанию запись потоков включена на стороне WCS-сервера.
Для отключения в конфиг /usr/local/FlashphonerWebCallServer/conf/flashphoner.properties следует добавить

record_streams=false

Настройка

record_flash_published_streams=true

включает запись потоков, опубликованных при помощи Flash, RTMP-кодировщика или с другого RTMP-сервера.

Настройка

record_rtsp_streams=true

включает запись потоков, захваченных с RTSP IP-камер.

Запись потоков в контейнер MPEG-TS

По умолчанию, H264 потоки записываются в контейнер MP4, VP8 потоки - в контейнер WebM. Начиная со сборки 5.2.610, H264 потоки могут быть записаны в контейнер MPEG-TS при помощи настройки

record_h264_to_ts=true

Ограничения

1. VLC до версии 3.0.8 может не играть записи в контейнере TS.

2. При проигрывании в  VLC может не работать перемотка.

Формирование имени файла записи потока

По умолчанию, имя файла формируется по шаблону, который задается настройкой stream_record_policy_template.

stream_record_policy_template=stream-{mediaSessionId}-{login}

Доступны следующие элементы шаблона:

ЭлементОписаниеМаксимальный размер
{streamName}Имя потока
{duration}Длительность файла, только для MP4-записей
{startTime}Время начала записи потока или фрагмента20 символов
{endTime}Время окончания записи потока или фрагмента20 символов
{startTimeMillis}Время сервера на момент начала записи потока или фрагмента20 символов
{endTimeMillis}Время сервера на момент окончания записи потока или фрагмента20 символов
{sessionId}Идентификатор сессии в кодировке BASE6460 символов
{mediaSessionId}Идентификатор медиасессии36 символов
{login}Логин32 символа
{audioCodec}Аудиокодек4 символа
{videoCodec}Видеокодек4 символа

Например, настройка

stream_record_policy_template={streamName}

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

ffmpeg -re -i BigBuckBunny.mp4 -preset ultrafast -acodec aac -vcodec h264 -strict -2 -f flv rtmp://test1.flashphoner.com:1935/live/stream_ffmpeg

будет записан в файл stream_ffmpeg.mp4.

Расширение файла добавляется в зависимости от параметров потока и контейнера: mp4 для H264+AAC и webm для VP8+opus.

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

encode_record_name=true,HEX

При этом имя файла будет закодировано шестнадцатиричным числом. Настройка

encode_record_name=true,BASE64

кодирует имя файла при помощи BASE64.

Другой способ экранирования недопустимых символов - их удаление при помощи параметра exclude_record_name_characters. По умолчанию

exclude_record_name_characters=/

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

exclude_record_name_characters=:.,/

Ротация файлов записей

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

record_rotation=20

определяет длительность фрагмента в 20 секунд, а настройка

record_rotation=10M

задает объем фрагмента в 10 мегабайт.

Если шаблон имени файла содержит элемент {startTime}, в имя файла подставляется время начала записи фрагмента. Если шаблон содержит элемент {endTime}, в имя файла подставляется время окончания записи фрагмента. Например, при настройках

record_rotation=20
stream_record_policy_template={streamName}-{startTime}-{endTime}

фрагменты записи потока test именуются следующим образом

test-1553577643961-1553577663988_1.mp4
test-1553577663989-1553577683997_2.mp4
test-1553577683997-1553577701626_3.mp4
...

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

При необходимости, нумерация может быть отключена настройкой

record_rotation_index_enabled=false

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

Вычисление времени начала, окончания и длительности записи

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

stream_record_policy_template={streamName}-{startTime}-{endTime}-{duration}

В сборке 5.2.635 добавлена возможность указать время начала и окончания записи по часам сервера

stream_record_policy_template={streamName}-{startTimeMillis}-{endTimeMillis}

При этом метки времени в потоке в общем случае будут отличаться от показаний часов сервера.

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

record_audio_buffer_max_size=100

По умолчанию, размер буфера установлен в 100 пакетов.

Скрипт обработки записанных файлов

Настройка on_record_hook_script указывает на shell-скрипт, который вызывается по завершении записи потока.

По умолчанию скрипт располагается в каталоге /usr/local/FlashphonerWebCallServer/bin:

on_record_hook_script=/usr/local/FlashphonerWebCallServer/bin/on_record_hook.sh

но может быть размещен в любом другом месте под другим именем, например:

on_record_hook_script=/opt/on_record.sh

Этот скрипт можно использовать для копирования или перемещения записи потока из директории WCS_HOME/records в другое место по завершении записи.

Пример:

STREAM_NAME=$1
SRC_FILE=$2
SRC_DIR="/usr/local/FlashphonerWebCallServer/records/"
REPLACE_STR="/var/www/html/stream_records/$STREAM_NAME-"
DST_FILE="${SRC_FILE/$SRC_DIR/$REPLACE_STR}"
cp $SRC_FILE $DST_FILE

Здесь

  • $1 - имя потока
  • $2 - абсолютное имя файла записи потока
  • по завершении записи потока файл записи копируется в директорию /var/www/html/stream_records/

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

Директория для записанных файлов

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

record_dir=/usr/local/FlashphonerWebCallServer/records

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

Настройка частоты дискретизации аудио при записи

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

record_audio_codec_sample_rate=48000

В данном случае частота дискретизации будет установлена в 48 кГц.

Настройка размещения атома moov в метаданных записи

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

mp4_container_moov_first=true

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

mp4_container_moov_first_reserve_space=true

Размер резервируемой области устанавливается в килобайтах настройкой

mp4_container_moov_reserved_space_size=2048

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

Настройка битрейта аудио при записи с использованием кодека FDK

В сборке 5.2.428 добавлена возможность указать режим битрейта аудио дорожки при записи с использованием кодека FDK. По умолчанию, установлен режим 5 (переменный битрейт в среднем 112 кбит/с). Это значение может быть изменено при помощи настройки

record_fdk_aac_bitrate_mode=5

Возможные режимы битрейта:

  • 0 - постоянный битрейт
  • 1-5 - переменный битрейт

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

Настройка количества каналов звука в записи

В сборке 5.2.610 добавлена возможность указывать количество каналов звука в записи при помощи настройки

record_audio_codec_channels=2

По умолчанию, количество каналов установлено в 2 (стерео). Чтобы записать поток с моно звуком, необходимо указать

record_audio_codec_channels=1

Настройка производительности записи под высокими нагрузками

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

file_recorder_thread_pool_max_size=4

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

Клиентская часть

При включении записи потоков на сервере, будет ли записан поток, или нет, зависит от значения параметра record, переданного функции createStream в скрипте публикующего клиента:

  • true - поток, опубликованный с использованием этого клиента, будет записан;
  • false - поток не будет записан.

Например, в скрипте веб-приложения Stream Recording recording.htmlrecording.js, содержится следующий код:

function publishStream(session) {
    var streamName = $('#url').val().split('/')[3];
    session.createStream({
        name: streamName,
        display: localVideo,
        record: true,
        receiveVideo: false,
        receiveAudio: false
    ...
    }).publish();
}

Запись потоков по требованию

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

REST-запрос должен быть HTTP/HTTPS POST запросом в таком виде:

  • HTTP: http://streaming.flashphoner.com:8081/rest-api/recorder/startup
  • HTTPS: https://streaming.flashphoner.com:8444/rest-api/recorder/startup

Здесь:

  • streaming.flashphoner.com - адрес WCS-сервера
  • 8081 - стандартный REST / HTTP порт WCS-сервера
  • 8444 - стандартный HTTPS порт
  • rest-api - обязательный префикс
  • /recorder/startup - используемый REST-вызов

REST-методы и статусы ответа

REST-метод

Пример тела REST-запроса

Пример тела REST-ответа

Статусы ответа

Описание

/stream/startRecording,

/recorder/startup


{
 "mediaSessionId": "5a072377-73c1-4caf-abd3",
  "config": {
    "fileTemplate": "{streamName}-{startTime}-{endTime}",
    "rotation": "20M"
  }
}

404 - Not found

500 - Internal error


Начать запись потока в указанной медиасессии


/stream/stopRecording,

/recorder/terminate

{
 "mediaSessionId": "5a072377-73c1-4caf-abd3"
}

404 - Not found

500 - Internal error

Завершить запись потока в указанной медиасессии
/recorder/find_all
[
    {
        "fileName": "9c3e-test-1563776083752-{endTime}.mp4", 
        "mediaSessionId": "5a072377-73c1-4caf-abd3"
    }
]

404 - Not found

500 - Internal error

Найти записываемые сессии

Параметры

Имя параметра

Описание

Пример

mediaSessionId

Идентификатор сессии

5a072377-73c1-4caf-abd3

configНастройки записи, имеют приоритет над настройками сервера
fileTemplateШаблон имени файла записи{streamName}-{startTime}-{endTime}
rotationВключает/отключает ротацию файлов и способ нарезки (время или объем)
20M

Логика работы записи по требованию выглядит следующим образом:

  • При вызове REST API /recorder/startup завершается текущая запись, если она идет в данный момент.
  • Стартует новая запись, при этом применяются переданные через REST настройки.
  • Если какая-либо из настроек не передана, применяется соответствующая настройка сервера.

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

/recorder/startup
{
  "mediaSessionId":"1234567890abcdefgh",
  "config": {
    "fileTemplate": "test",
    "rotation": "disabled"
  }
}

REST запрос /recorder/find_all возвращает список сессий, записываемых в данный момент. В списке отражаются как записи по требованию, запущенные через REST API, так и записи, инициированные через WebSDK:

[
    {
        "fileName": "003f-1563776713987-{endTime}.mp4", 
        "mediaSessionId": "5af9c820-ac49-11e9-9f06-693cb47c4042"
    }, 
    {
        "fileName": "stream-57882100-ac49-11e9-afdd-6752f5be57a9-jtdvnittjkrd8rsc3dnfbger2o.mp4", 
        "mediaSessionId": "57882100-ac49-11e9-afdd-6752f5be57a9"
    }
]

Получение имени записанного файла

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

1. На сервере имя файла получает скрипт обработки записанных файлов по окончании записи

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

stream_record_policy_template={streamName}-{mediaSessionId}

3. При использовании WebSDK для записи потока, имя записанного файла можно получить при помощи функции getRecordInfo()

    ...
    }).on(STREAM_STATUS.UNPUBLISHED, function (stream) {
        setStatus(stream.status());
        showDownloadLink(stream.getRecordInfo());
        onStopped();
    })
    ...

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

record_stop_timeout=15

Загрузка и воспроизведение записанного файла

Записанный файл доступен во встроенном веб-сервере WCS по прямой ссылке вида

https://test.flashphoner.com:8444/client/records/stream.mp4

Здесь

  • test.flashphoner.com - URL WCS сервера
  • stream.mp4 - имя записанного файла

По умолчанию, WCS возвращает заголовок

Content-Disposition: inline;filename="stream.mp4"

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

record_response_content_disposition_header_value=inline

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

record_response_content_disposition_header_value=attachment

Известные проблемы

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

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

3. Дата создания файла записывается в метаданные только в контейнере MP4. 

4. Скрипт обработки записанных файлов требует повышения прав для копирования и других операций над файлами записей на виртуальных машинах Amazon

Симптомы: операции над записанными файлами не выполняются

Решение: использовать sudo для файловых операций и вызова внешних скриптов, если WCS установлен на виртуальной машине Amazon, например

sudo cp $SRC_FILE $DST_FILE