Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

ПолеТипОписание
timestampUInt64Метка времени
ipIPv4Адрес сервера
mediaSessionIdStringИдентификатор медиасессий
streamNameStringИмя потока
videoProfileIdUInt32Идентификатор профиля видео
videoWidthUInt32Высота картинки
videoHeightUInt32Ширина картинки
videoFrameRateUInt32Частота кадров в секунду
videoKframesUInt64Количество ключевых кадров (I-frame)
videoPframesUInt64Количество промежуточных кадров (P-frame)
videoBframesUInt64Количество двунаправленных кадров (B-frames)
videoRateUInt64Битрейт видео, бит/с
audioRateUInt64Битрейт аудио, бит/с
videoSyncTimeUInt64Значение синхронизации видео
audioSyncTimeUInt64Значение синхронизации аудио
videoTimestampUInt64Метка времени из видеопакета
audioTimestampUInt64Метка времени из аудиопакета
lastKeyFrameSyncTimeUInt64Значение синхронизации видео из последнего ключевого кадра
sendNACKUInt64Количество отправленных NACK
recvNACKUInt64Количество полученных NACK
videoFramesLostUInt64Количество потерянных кадров видео
audioPacketsLostUInt64Количество потерянных пакетов аудио
audioPlaybackSpeedFloat32Скорость публикации/проигрывания аудио
videoPlaybackSpeedFloat32Скорость публикации/проигрывания видео

Данные о нарезке HLS потока (таблица HlsStreamEvents)

В сборке 5.2.1917 добавлен сбор данных о событиях определенных HLS потоков

ПолеТипОписание
timestampUInt64Метка времени
ipIPv4Адрес сервера
severityUInt8Уровень события: INFO, WARNING, ERROR
messageTypeUInt16Тип события
streamIdStringИдентификатор HLS потока (имя)
variantNameStringИмя варианта качества
segmentIdStringИдентификатор сегмента
messageStringОписание события в том виде, как залогировано

Данные о сегментах HLS потока (таблица HlsSegmenterEvents)

В сборке 5.2.1917 добавлен сбор данных о сегментах определенных HLS потоков

ПолеТипОписание
timestampUInt64Метка времени
ipIPv4Адрес сервера
streamIdStringИдентификатор HLS потока (имя)
variantNameStringИмя варианта качества
segmentIdStringИдентификатор сегмента
segmentStartPtsUInt64Начальный PTS сегмента
videoStartPtsUInt64Начальный PTS  видео дорожки
audioStartPtsUInt64Начальный PTS  аудио дорожки
videoWidthUInt32Ширина картинки
videoHeightUInt32Высота картинки
videoFrameCountUInt32Количество кадров видео
audioPacketCountUInt32Количество пакетов аудио
segmentDurationUInt64Длительность сегмента, мс
independentBoolНезависимый сегмент
gapBoolGAP  сегмент
discontinuityBoolDISCONTINUTY сегмент
segmentIntervalUInt64Интервал между сегментами, мс
partialBoolЧастичный сегмент
playbackSpeedFloat32Скорость проигрывания

Данные о подписчиках HLS потока (таблица HlsClientEvents)

В сборке 5.2.1929 добавлен сбор данных о подписчиках определенных HLS потоков

ПолеТипОписание
creationTimeUInt64Время подключения подписчика
responseTimeUInt64Время ответа на запрос подписчика
streamIdStringИдентификатор HLS потока (имя)
variantNameStringИмя варианта качества
uriStringURI плейлиста
localIpIPv4Адрес сервера
remoteIpIPv4Адрес клиента
remotePortUInt32TCP  порт, с которого подключился клиента
userAgentStringЗначение заголовка User-Agent, полученное от клиента
httpStatusUInt32Статус ответа на запрос клиента
clientIdUInt64Идентификатор клиентской сессии

Данные о метриках микшера (таблица MixerEvent)

В сборке 5.2.1923 добавлен сбор данных о метриках определенных микшеров

ПолеТипОписание
timestampUInt64Метка времени
mixerMediaSessionIdStringИдентификатор медиасессии микшера
mixerStreamNameStringИмя выходного потока микшера
mediaSessionIdStringИдентификатор входящего потока микшера
streamNameStringИмя входящего потока
mixerAverageTickTimeInMsInt64Среднее время одного такта микширования, мс
audioMixerSyncInt64Значение синхронизации аудио в выходном потоке микшера
videoMixerSyncInt64Значение синхронизации видео в выходном потоке микшера
nextAudioDataTimeInt64Время следующего аудио пакета
nextVideoDataTimeInt64Время следующего видео пакета
audioBufferedInt64Количество аудио пакетов в буфере входящего потока
videoBufferedInt64Количество видео пакетов в буфере входящего потока
audioDropsCounterInt64Количество отброшенных аудио пакетов входящего потока
audioDropsSizeInBytesInt64Объем отброшенных данных аудио в байтах
videoDropsCounterInt64Количество отброшенных видео пакетов входящего потока
videoDropsSizeInBytesInt64Объем отброшенных данных видео в байтах
videoFpsInt64Частота кадров выходного потока микшера в секунду
audioRateDOUBLEБитрейт аудио выходного потока микшера, бит/с
videoRateDOUBLEБитрейт видео выходного потока микшера, бит/с
eventTypeUInt32Тип события микшера
eventPayloadStringОписание события микшера

Настройка

Установка и настройка ClickHouse

...

Code Block
languagesql
themeRDark
titlewcs_clickhouse.sql
collapsetrue
CREATE DATABASE IF NOT EXISTS wcs;
 
DROP TABLEDICTIONARY IF EXISTS wcs.StreamEventDictionaryStreamEvents;
 
DROP TABLEDICTIONARY IF EXISTS wcs.ConnectionEventDictionaryConnectionEvents;
 
DROP TABLEDICTIONARY IF EXISTS wcs.CDNEventDictionaryCDNEvents;
 
DROP TABLEDICTIONARY IF EXISTS wcs.StreamEventTypesDictionaryHlsStreamEventType;
 
DROP TABLEDICTIONARY IF EXISTS wcs.ConnectionEventTypesDictionaryHlsStreamEventSeverity;
 
DROP TABLEDICTIONARY IF EXISTS wcs.CDNEventTypesDictionaryMixerEvents;

DROP TABLEDICTIONARY IF EXISTS wcs.MediaSessionEventsDictionaryBufferStateTypes;
 
DROP TABLE IF EXISTS wcs.HlsStreamEventsStreamEvent;
 
DROP TABLE IF EXISTS wcs.HlsSegmenterEventsConnectionEvent;
 
DROP TABLE IF EXISTS wcs.HlsStreamEventSeverityCDNEvent;
 
DROP TABLE IF EXISTS wcs.HlsStreamEventTypeStreamEventTypes;
 
DROP TABLE IF EXISTS wcs.HlsClientEventsConnectionEventTypes;
 
DROP TABLE IF EXISTS wcs.MixerEventCDNEventTypes;

DROP TABLE IF EXISTS wcs.MixerEventTypesMediaSessionEvents;

DROP DICTIONARYTABLE IF EXISTS wcs.DictionaryStreamEventsHlsStreamEvents;
 
DROP DICTIONARYTABLE IF EXISTS wcs.DictionaryConnectionEvents;
 
DROP DICTIONARYHlsSegmenterEvents;

DROP TABLE IF EXISTS wcs.HlsStreamEventSeverity;

DROP TABLE IF EXISTS wcs.HlsStreamEventType;

DROP TABLE IF EXISTS wcs.HlsClientEvents;

DROP TABLE IF EXISTS wcs.DictionaryCDNEventsMixerEvent;

DROP DICTIONARYTABLE IF EXISTS wcs.DictionaryHlsStreamEventTypeMixerEventTypes;

DROP DICTIONARYTABLE IF EXISTS wcs.DictionaryHlsStreamEventSeverityRtmpInBufferEvent;

DROP TABLE IF EXISTS wcs.AudioRecoveryEvent;

DROP DICTIONARYTABLE IF EXISTS wcs.DictionaryMixerEventsBufferStateTypes;

CREATE TABLE wcs.ConnectionEventTypes
(
    `id` UInt32,
    `type` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;
 
INSERT INTO wcs.ConnectionEventTypes VALUES (0, 'CONNECTED'), (1, 'DISCONNECTED');
 
CREATE TABLE wcs.StreamEventTypes
(
    `id` UInt32,
    `type` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;
 
INSERT INTO wcs.StreamEventTypes VALUES (0,'CREATED'),(1,'LOCAL_SDP_CREATED'),(2,'REMOTE_SDP_RECEIVED'),(3,'ICE_STARTED'),(4,'ICE_COMPLETE'),(5,'DTLS_STARTED'),(6,'DTLS_COMPLETE'),(7,'INITIALIZED'),(8,'DISPOSING'),(9,'DISPOSED'),(10,'AUDIO_RECEIVED'),(11,'VIDEO_RECEIVED'),(12,'VIDEO_KFRAME_RECEIVED'),(13,'AUDIO_RTCP_RECEIVED'),(14,'VIDEO_RTCP_RECEIVED'),(15,'RESOLUTION_RECEIVED'),(16,'VIDEO_ENCODER_CREATED'),(17,'AUDIO_ENCODER_CREATED'),(18,'VIDEO_ENCODER_DISPOSED'),(19,'AUDIO_ENCODER_DISPOSED'),(20,'TERMINATED'),(21,'AUDIO_SENT'),(22,'VIDEO_SENT'),(23,'VIDEO_JITTER_BUFFER_STALL'),(24,'SENT_PLI'),(25,'RECEIVED_PLI'),(26,'SYNC_BUFFER_FULL'),(27,'SYNC_FORCE_FAILED'),(28,'SYNC_SHIFT'),(29,'SYNC_DEVIATION'),(30,'VIDEO_STATS'),(31,'RECORD');
 
CREATE TABLE wcs.CDNEventTypes
(
    `id` UInt32,
    `type` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;
 
INSERT INTO wcs.CDNEventTypes VALUES (0, 'STATE'), (1, 'CDN_STATE'), (2, 'VERSION'), (3, 'ACL_REFRESH'), (4, 'ACL_UPDATE');
 
CREATE DICTIONARY wcs.DictionaryStreamEvents (
    `id` UInt16,
    `type` String DEFAULT ''
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(
 host 'localhost'
 port 9000
 user 'default'
 password ''
 db 'wcs'
 table 'StreamEventTypes'
))   
LAYOUT(FLAT())
LIFETIME(300);
 
CREATE DICTIONARY wcs.DictionaryConnectionEvents (
    `id` UInt16,
    `type` String DEFAULT ''
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(
 host 'localhost'
 port 9000
 user 'default'
 password ''
 db 'wcs'
 table 'ConnectionEventTypes'
))   
LAYOUT(FLAT())
LIFETIME(300);
 
CREATE DICTIONARY wcs.DictionaryCDNEvents (
    `id` UInt16,
    `type` String DEFAULT ''
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(
 host 'localhost'
 port 9000
 user 'default'
 password ''
 db 'wcs'
 table 'CDNEventTypes'
))   
LAYOUT(FLAT())
LIFETIME(300);
 
CREATE TABLE wcs.StreamEvent
(
    `timestamp` UInt64,
    `ip` IPv4,
    `sessionId` String,
    `mediaSessionId` String,
    `streamName` String,
    `eventType` UInt64,
    `eventPayload` String
)
ENGINE = MergeTree()
ORDER BY (sessionId, mediaSessionId, streamName)
SETTINGS index_granularity = 8192;
 
CREATE TABLE wcs.ConnectionEvent
(
    `timestamp` UInt64,
    `ip` IPv4,
    `sessionId` String,
    `eventType` UInt64,
    `eventPayload` String
)
ENGINE = MergeTree()
ORDER BY (timestamp, sessionId)
SETTINGS index_granularity = 8192;
 
CREATE TABLE wcs.CDNEvent
(
    `timestamp` UInt64,
    `ip` IPv4,
    `nodeId` String,
    `eventType` UInt64,
    `eventPayload` String
)
ENGINE = MergeTree()
ORDER BY (nodeId, eventType)
SETTINGS index_granularity = 8192;

CREATE TABLE wcs.MediaSessionEvents
(
    `timestamp` UInt64,
    `ip` IPv4,
    `mediaSessionId` String,
    `streamName` String,
    `videoProfileId` UInt32,
    `videoWidth` UInt32,
    `videoHeight` UInt32,
    `videoFrameRate` UInt32,
    `videoKframes` UInt64,
    `videoPframes` UInt64,
    `videoBframes` UInt64,
    `videoRate` UInt64,
    `audioRate` UInt64,
    `videoSyncTime` UInt64,
    `audioSyncTime` UInt64,
    `videoTimestamp` UInt64,
    `audioTimestamp` UInt64,
    `lastKeyFrameSyncTime` UInt64,
    `sendNACK` UInt64,
    `recvNACK` UInt64,
    `videoFramesLost` UInt64,
    `audioPacketsLost` UInt64,
)
ENGINE  =   `audioPlaybackSpeed` Float32,
    `videoPlaybackSpeed` Float32
)
ENGINE = MergeTree()
ORDER BY (mediaSessionId, streamName)
SETTINGS index_granularity = 8192;

CREATE TABLE wcs.HlsSegmenterEvents
(
    `timestamp` UInt64,
    `ip` IPv4,
    `streamId` String,
    `variantName` String,
    `segmentId` String,
    `segmentStartPts` UInt64,
    `videoStartPts` UInt64,
    `audioStartPts` UInt64,
    `videoWidth` UInt32,
    `videoHeight` UInt32,
    `videoFrameCount` UInt32,
    `audioPacketCount` UInt32,
    `segmentDuration` UInt64,
    `independent` Bool,
    `gap` Bool,
    `discontinuity` Bool,
    `segmentInterval` UInt64,
    `partial` Bool,
    `playbackSpeed` Float32
)
ENGINE = MergeTree()
ORDER BY (streamId)
SETTINGS index_granularity = 8192;

CREATE TABLE wcs.HlsStreamEventSeverity
(
    `id` UInt8,
    `type` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;

INSERT INTO wcs.HlsStreamEventSeverity VALUES (0, 'INFO'), (1, 'WARNING'), (2, 'ERROR');

CREATE TABLE wcs.HlsStreamEventType
(
    `id` UInt16,
    `type` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;

INSERT INTO wcs.HlsStreamEventType
VALUES (0, 'PLAYBACK_SPEED'), (1, 'FPS_CHANGED'), (2, 'GAP'), (3, 'RESOLUTION_CHANGED'), (4, 'DISCONTINUITY'), (5, 'TASK_SKIPPED'), (6, 'NO_KYE_FRAME'), (7, 'NO_VIDEO'), (8, 'NO_AUDIO'), (9, 'SEGMENT_INTERVAL'), (10, 'OTHER');

CREATE DICTIONARY wcs.DictionaryHlsStreamEventSeverity
(
   `id` UInt8,
   `type` String DEFAULT ''
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(
 host 'localhost'
 port 9000
 user 'default'
 password ''
 db 'wcs'
 table 'HlsStreamEventSeverity'
))
LAYOUT(FLAT())
LIFETIME(300);

CREATE DICTIONARY wcs.DictionaryHlsStreamEventType
(
   `id` UInt16,
   `type` String DEFAULT ''
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(
 host 'localhost'
 port 9000
 user 'default'
 password ''
 db 'wcs'
 table 'HlsStreamEventType'
))
LAYOUT(FLAT())
LIFETIME(300);

CREATE TABLE wcs.HlsStreamEvents
(
    `timestamp` UInt64,
    `ip` IPv4,
    `severity` UInt8,
    `messageType` UInt16,
    `streamId` String,
    `variantName` String,
    `segmentId` String,
    `message` String
)
ENGINE = MergeTree()
ORDER BY (streamId)
SETTINGS index_granularity = 8192; 

CREATE TABLE wcs.HlsClientEvents
(
    `creationTime` UInt64,
    `responseTime` UInt64,
    `streamId` String,
    `variantName` String,
    `uri` String,
    `localIp` IPv4,
    `remoteIp` IPv4,
    `remotePort` UInt32,
    `userAgent` String,
    `httpStatus` UInt32,
    `clientId` UInt64
)
ENGINE = MergeTree()
ORDER BY (creationTime)
SETTINGS index_granularity = 8192;

CREATE TABLE wcs.MixerEvent
(
    `timestamp` UInt64,
    `mixerMediaSessionId` String,
    `mixerStreamName` String,
    `mediaSessionId` String,
    `streamName` String,
    `mixerAverageTickTimeInMs` Int64,
    `audioMixerSync` Int64,
    `videoMixerSync` Int64,
    `nextAudioDataTime` Int64,
    `nextVideoDataTime` Int64,
    `audioBuffered` Int64,
    `videoBuffered` Int64,
    `audioDropsCounter` Int64,
    `audioDropsSizeInBytes` Int64,
    `videoDropsCounter` Int64,
    `videoDropsSizeInBytes` Int64,
    `videoFps` Int64,
    `audioRate` DOUBLE,
    `videoRate` DOUBLE,
    `eventType` UInt32,
    `eventPayload` String
)
ENGINE = MergeTree()
ORDER BY timestamp
SETTINGS index_granularity = 8192;

CREATE TABLE wcs.MixerEventTypes
(
    `id` UInt32,
    `type` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;

INSERT INTO wcs.MixerEventTypes VALUES (0, 'nullEvent'), (1, 'dropBallastAudio'), (2, 'dropBallastVideo'), (3, 'audioNotBuffered'), (4, 'videoNotBuffered'), (5, 'audioBufferExhausted'), (6, 'videoBufferExhausted'), (7, 'alignStreamFailed'), (8, 'alignStreamDropAudio'), (9, 'alignStreamDropVideo'), (10, 'rateOutOfBoundsAudio'), (11, 'rateOutOfBoundsVideo');

CREATE DICTIONARY wcs.DictionaryMixerEvents (
    `id` UInt16,
    `type` String DEFAULT ''
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(
 host 'localhost'
 port 9000
 user 'default'
 password ''
 db 'wcs'
 table 'MixerEventTypes'
))
LAYOUT(FLAT())
LIFETIME(300);

5. Создайте пользователя wcs и дайте ему права на таблицы в базе данных wcs

Code Block
languagebash
themeRDark
cat wcs_clickhouse_users.sql | clickhouse-client -mn
Code Block
languagesql
themeRDark
titlewcs_clickhouse_users.sql
collapsetrue
CREATE USER IF NOT EXISTS wcs IDENTIFIED BY 'wcs';
GRANT ALL ON wcs.* TO wcs WITH GRANT OPTION;

6. Отключите управление пользователями для пользователя default, указав в файле /etc/clickhouse-server/users.xml параметр

Code Block
languagexml
themeRDark
            <access_management>0</access_management>

7. Перезапустите ClickHouse

Code Block
languagebash
themeRDark
systemctl restart clickhouse-server

Настройка WCS

...



CREATE TABLE wcs.RtmpInBufferEvent
(
    `timestamp` UInt64,
    `streamClockTime` UInt64,
    `mediaSessionId` String,
    `streamName` String,
    `nextAudioDataTime` Int64,
    `nextVideoDataTime` Int64,
    `audioBuffered` Int64,
    `videoBuffered` Int64,
    `maximumAllowedBuffer` Int64,
    `bufferingCounter` Int64,
    `lastAudioDataTime` Int64,
    `lastVideoDataTime` Int64,
    `bufferState` UInt32
)
ENGINE = MergeTree()
ORDER BY timestamp
SETTINGS index_granularity = 8192;

CREATE TABLE wcs.BufferStateTypes
(
    `id` UInt32,
    `type` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;

INSERT INTO wcs.BufferStateTypes VALUES (0, 'BUFFERING'), (1, 'HOLD'), (2, 'TERMINATED'), (3, 'OVERFLOW'), (4, 'PASSTHROUGH');

CREATE DICTIONARY wcs.DictionaryBufferStateTypes (
    `id` UInt16,
    `type` String DEFAULT ''
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(
 host 'localhost'
 port 9000
 user 'default'
 password ''
 db 'wcs'
 table 'BufferStateTypes'
))
LAYOUT(FLAT())
LIFETIME(300);

CREATE TABLE wcs.AudioRecoveryEvent
(
    `timestamp` UInt64,
    `mediaSessionId` String,
    `type` UInt32,
    `rtpTimestamp` UInt64
)
ENGINE = MergeTree()
ORDER BY rtpTimestamp
SETTINGS index_granularity = 8192;

5. Создайте пользователя wcs и дайте ему права на таблицы в базе данных wcs

Code Block
languagebash
themeRDark
cat wcs_clickhouse_users.sql | clickhouse-client -mn
Code Block
languagesql
themeRDark
titlewcs_clickhouse_users.sql
collapsetrue
CREATE USER IF NOT EXISTS wcs IDENTIFIED BY 'wcs';
GRANT ALL ON wcs.* TO wcs WITH GRANT OPTION;

6. Отключите управление пользователями для пользователя default, указав в файле /etc/clickhouse-server/users.xml параметр

Code Block
languagexml
themeRDark
            <access_management>0</access_management>

7. Перезапустите ClickHouse

Code Block
languagebash
themeRDark
systemctl restart clickhouse-server

Настройка WCS

Сбор данных в БД ClickHouse включается настройкой, в которой перечисляются типы отправляемых данных

Code Block
themeRDark
rels_enabled=CONNECTION,STREAM,CDN,MEDIA_SESSION

Доступны следующие типы данных:

CONNECTION, STREAM, CDN, MEDIA_SESSION, HLS_SEGMENTER, HLS_STREAM, HLS_CLIENT, MIXER, AUDIO_RECOVERY, RTMP_IN_BUFFER

ТипОписание
CONNECTIONСобытия клиенсткой сессии
STREAMСобытия потока
CDNСобытия CDN
MEDIA_SESSIONСобытия медиа сессии
HLS_SEGMENTERДанные о нарезке HLS потоков
HLS_STREAMСобытия HLS  потоков
HLS_CLIENTСтатистика HLS клиентов
MIXERСобытия микшера
AUDIO_RECOVERYСтатистика потерь и восстановления аудиопакетов
RTMP_IN_BUFFERСтатистика буфера входящих RTMP потоков

Адрес сервера ClickHouse, база данных и протокол задаются настройками

Code Block
themeRDark
rels_enabled=true

...

_client_type=HTTP
rels_database_address=http://clickhouseserver:8123/wcs?user=wcs&password=wcs

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

Code Block
themeRDark
rels_client_type=JDBC
rels_database_address=jdbc:clickhouse://clickhouseserver:8123/wcs?user=wcs&password=wcs

...

Code Block
themeRDark
rels_enabled=false

2. Перезагрузите настройки сервера из интерфейса командной строки

...

Code Block
themeRDark
rels_enabled=false

3. Перезагрузите настройки сервера из интерфейса командной строки

...