...
Code Block |
---|
|
rtp_activity_video=false |
Если браузер Chrome публикует пустое видео при занятой веб-камере
Некоторые версии браузера Chrome не возвращают ошибку в случае, если веб-камера занята другим процессом, а публикуют поток с пустым видео (черный экран). Остановить публикацию в этом случае можно двумя способами: при помощи JavaScript и HTML5 на клиенте, или при помощи настройки на сервере.
Остановка публикации потока на стороне клиента
Видеодорожка, созданная браузером Chrome для занятой камеры, останавливается в пределах первой секунды публикации, затем поток публикуется уже без видео. При этом состояние видеодорожки (переменная readyState
) меняется на ended
, и генерируется соответствующее событие onended
, которое может быть перехвачено веб-приложением. Для того, чтобы использовать это событие:
1. Добавляем в скрипт веб-приложения функцию регистрации обработчика события onended, в котором завершаем публикацию при помощи stream.stop()
...
...
Контроль наличия медиа трафика работает только при публикации, но не при проигрывании потоков.
Отключение контроля активности видео и аудио дорожек по имени потока
В сборке 5.2.1784 добавлена возможность отключить контроль активности видео и аудио дорожек в потоках, имя которых совпадает с регулярным выражением
Code Block |
---|
|
rtp_activity_audio_exclude=stream1
rtp_activity_video_exclude=stream1 |
Это может быть полезно для потоков, трафик в которых может останавливаться на длительное время, например, для потоков с экрана или окна приложения:
Code Block |
---|
|
rtp_activity_audio_exclude=.*-screen$
rtp_activity_video_exclude=.*-screen$ |
В данном случае контроль активности не будет применяться к потокам с именами conference-123-user-456-screen
Если браузер Chrome публикует пустое видео при занятой веб-камере
Некоторые версии браузера Chrome не возвращают ошибку в случае, если веб-камера занята другим процессом, а публикуют поток с пустым видео (черный экран). Остановить публикацию в этом случае можно двумя способами: при помощи JavaScript и HTML5 на клиенте, или при помощи настройки на сервере.
Остановка публикации потока на стороне клиента
Видеодорожка, созданная браузером Chrome для занятой камеры, останавливается в пределах первой секунды публикации, затем поток публикуется уже без видео. При этом состояние видеодорожки (переменная readyState
) меняется на ended
, и генерируется соответствующее событие onended
, которое может быть перехвачено веб-приложением. Для того, чтобы использовать это событие:
1. Добавляем в скрипт веб-приложения функцию регистрации обработчика события onended, в котором завершаем публикацию при помощи stream.stop()
Code Block |
---|
|
function addVideoTrackEndedListener(localVideo, stream) {
var videoTrack = extractVideoTrack(localVideo);
if (videoTrack && videoTrack.readyState == 'ended') {
console.error("Video source error. Disconnect...");
stream.stop();
} else if (videoTrack) {
videoTrack.onended = function (event) {
console.error("Video source error. Disconnect...");
stream.stop();
};
}
} |
2. Добавляем функцию удаления обработчика события при завершении публикации
Code Block |
---|
|
function removeVideoTrackEndedListener(localVideo) {
var videoTrack = extractVideoTrack(localVideo);
if(videoTrack) {
videoTrack.onended = null;
}
} |
3. Добавляем функцию извлечения видеодорожки
Code Block |
---|
|
function extractVideoTrack(localVideo) {
return localVideo.firstChild.srcObject.getVideoTracks()[0];
} |
4. При публикации потока регистрируем обработчик события
Code Block |
---|
|
session.createStream({
name: streamName,
display: localVideo,
...
}).on(STREAM_STATUS.PUBLISHING, function (stream) {
addVideoTrackEndedListener(localVideo, stream);
setStatus("#publishStatus", STREAM_STATUS.PUBLISHING);
onPublishing(stream);
...
}).publish(); |
5. При завершении публикации потока удаляем обработчик события
Code Block |
---|
|
function onPublishing(stream) {
$("#publishBtn").text("Stop").off('click').click(function () {
$(this).prop('disabled', true);
removeVideoTrackEndedListener(localVideo);
stream.stop();
}).prop('disabled', false);
$("#publishInfo").text("");
} |
Контроль активности видеодорожки в потоке на стороне сервера
Контроль активности видео в публикуемых потоках на сервере включается при помощи следующей настройки в файле flashphoner.properties
Code Block |
---|
|
rtp_activity_video=true |
В этом случае, если в публикуемом потоке нет видео, публикация остановится через 60 секунд.
Публикация только видео при помощи ограничений
В некоторых случаях необходимо опубликовать только видео при занятом микрофоне, например, если публикация производится одновременно с голосовым звонком. Для того, чтобы браузер не запрашивал доступ к микрофону, необходимо указать в ограничениях, что будет опубликовано только видео:
Code Block |
---|
|
session.createStream({
name: streamName,
display: localVideo,
constraints: {video: true, audio: false}
...
}).publish(); |
Публикация только аудио
В большинстве случаев, для публикации только аудио достаточно установить ограничения:
Code Block |
---|
|
session.createStream({
name: streamName,
display: localVideo,
stream.stop();
} else if (videoTrack) {
constraints: {video: false, audio: true}
...
videoTrack.onended = function (event) {
}).publish(); |
Публикация только аудио в браузере Safari
При попытке опубликовать аудио поток из браузера iOS Safari при помощи ограничений, браузер не высылает аудио пакеты. Для того, чтобы обойти это ограничение, необходимо опубликовать поток с видео, а затем заглушить видео в потоке
Code Block |
---|
|
session.createStream({
name: streamName,
console.error("Video source error. Disconnect...");display: localVideo,
constraints: {video: true, stream.stop();audio: true}
};...
}
} |
2. Добавляем функцию удаления обработчика события при завершении публикации
Code Block |
---|
|
function removeVideoTrackEndedListener(localVideo).on(STREAM_STATUS.PUBLISHING, function (stream) {
var videoTrack = extractVideoTrackstream.muteVideo(localVideo);
if(videoTrack) {
videoTrack.onended = null;
}
} |
3. Добавляем функцию извлечения видеодорожки
Code Block |
---|
|
function extractVideoTrack(localVideo) {
return localVideo.firstChild.srcObject.getVideoTracks()[0];
} |
...
В этом случае браузер iOS Safari будет высылать в потоке пустые видео пакеты (темнота) и аудио пакеты.
Отключение нормализации ограничений по разрешению в браузере Safari
По умолчанию, WebSDK нормализует разрешение, указанное в ограничениях при публикации видеопотока из браузера Safari. При этом проверяется, не задана ли ширина либо высота картинки равной 0 и, если да, разрешение принудительно устанавливается в 320x240 или 640x480. Начиная со сборки WebSDK 0.5.28.2753.109 (хэш 149855cc050bf7512817104fd0104e9cce760ac4), существует возможность отключить нормализацию и передавать ограничения в браузер как есть, например:
Code Block |
---|
|
publishStream = session.createStream({
name: streamName,
display: localVideo,
...
}).on(STREAM_STATUS.PUBLISHING, function (stream) {
addVideoTrackEndedListener(localVideo, stream);
setStatus("#publishStatus", STREAM_STATUS.PUBLISHING);
disableConstraintsNormalization: true,
constraints: {
onPublishing(stream);video: {
...
}).publish(); |
5. При завершении публикации потока удаляем обработчик события
Code Block |
---|
|
function onPublishing(stream) {
$("#publishBtn").text("Stop").off('click').click(function () {
width: {ideal: 1024},
$(this).prop('disabled', true);height: {ideal: 768}
removeVideoTrackEndedListener(localVideo);
},
stream.stop();audio: true
}
}).prop('disabled', false);on(STREAM_STATUS.PUBLISHING, function (publishStream) {
$("#publishInfo").text("");
} |
Контроль активности видеодорожки в потоке на стороне сервера
...
...
});
publishStream.publish(); |
Исключение профилей кодирования H264
В сборке 5.2.620 добавлена возможность исключения определенных профилей кодирования H264 из SDP, отправляемого сервером браузеру. Исключаемые профили должны быть перечислены в настройке
Code Block |
---|
|
rtpwebrtc_sdp_activity_video=true |
В этом случае, если в публикуемом потоке нет видео, публикация остановится через 60 секунд.
Публикация только видео при помощи ограничений
В некоторых случаях необходимо опубликовать только видео при занятом микрофоне, например, если публикация производится одновременно с голосовым звонком. Для того, чтобы браузер не запрашивал доступ к микрофону, необходимо указать в ограничениях, что будет опубликовано только видео:
Code Block |
---|
language | jsh264_exclude_profiles=4d,64 |
---|
В данном случае из SDP будут исключены профили Main (4d) и High (64), останется только Baseline (42):
Code Block |
---|
|
a=rtpmap:102 session.createStream({
name: streamName,
display: localVideo,
constraints: {video: true, audio: false}
...
}).publish(); |
Публикация только аудио
В большинстве случаев, для публикации только аудио достаточно установить ограничения:
Code Block |
---|
|
session.createStream({
name: streamName,
display: localVideo,
constraints: {video: false, audio: true}
...
}).publish(); |
Публикация только аудио в браузере Safari
...
H264/90000
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:125 H264/90000
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:127 H264/90000
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:108 H264/90000
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f |
Такая настройка может быть полезна в случае, если какой-то из браузеров кодирует B-фреймы, например, с использованием высокого профиля кодирования при включенном аппаратном ускорении.
По умолчанию, профили не исключаются из SDP в том случае, если они поддерживаются браузером
Code Block |
---|
|
webrtc_sdp_h264_exclude_profiles= |
Управление типом публикуемого контента в Chromium браузерах
В некоторых случаях Chromium браузеры, основанные на сборке Chromium 91, агрессивно оценивают качество канала публикации, и сбрасывают разрешение ниже заданного, даже если канал подходит для публикации потока 720p или 1080p. В связи с этим, в сборке WebSDK 2.0.180 добавлена опция videoContentHint:
Code Block |
---|
|
session.createStream({
name: streamName,
display: localVideo,
constraints: {videocacheLocalResources: true,
audio: true}
receiveVideo: false,
...
}).on(STREAM_STATUS.PUBLISHING, function (stream) {receiveAudio: false,
stream.muteVideo(); videoContentHint: "detail"
...
}).publish(); |
В этом случае браузер iOS Safari будет высылать в потоке пустые видео пакеты (темнота) и аудио пакеты.
...
По умолчанию, WebSDK нормализует эта опция установлена в detail
и указывает браузеру удерживать разрешение, указанное заданное в ограничениях constraints при публикации видеопотока из браузера Safari. При этом проверяется, не задана ли ширина либо высота картинки равной 0 и, если да, разрешение принудительно устанавливается в 320x240 или 640x480. Начиная со сборки WebSDK 0.5.28.2753.109 (хэш 149855cc050bf7512817104fd0104e9cce760ac4), существует возможность отключить нормализацию и передавать ограничения в браузер как есть, например:. Однако, при публикации с некоторых веб камер, подключаемых по USB, браузер может в этом случае сбрасывать FPS. Если необходимо удерживать FPS, но разрешение публикации при этом не важно, необходимо установить опцию в motion
Code Block |
---|
|
publishStream = session.createStream({
...
disableConstraintsNormalizationname: truestreamName,
constraints: {
videodisplay: {localVideo,
widthcacheLocalResources: {ideal: 1024}true,
height: {ideal: 768}
}receiveVideo: false,
audioreceiveAudio: truefalse,
}
}).on(STREAM_STATUS.PUBLISHING, function (publishStream) {
videoContentHint: "motion"
...
});
publishStream.publish(); |
Исключение профилей кодирования H264
В сборке 5.2.620 добавлена возможность исключения определенных профилей кодирования H264 из SDP, отправляемого сервером браузеру. Исключаемые профили должны быть перечислены в настройке
Code Block |
---|
|
webrtc_sdp_h264_exclude_profiles=4d,64 |
В данном случае из SDP будут исключены профили Main (4d) и High (64), останется только Baseline (42):
Code Block |
---|
|
a=rtpmap:102 H264/90000
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:125 H264/90000
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:127 H264/90000
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:108 H264/90000
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f |
Такая настройка может быть полезна в случае, если какой-то из браузеров кодирует B-фреймы, например, с использованием высокого профиля кодирования при включенном аппаратном ускорении.
По умолчанию, профили не исключаются из SDP в том случае, если они поддерживаются браузером
Code Block |
---|
|
webrtc_sdp_h264_exclude_profiles= |
Управление типом публикуемого контента в Chromium браузерах
...
В сборке WebSDK 2.0.204 в пример Media Devices добавлен пример установки опции videoContentHint
Image Added
Управление FPS в браузере Firefox
По умолчанию, Firefox публикует видео с максимальным FPS, который ему показывает драйвер используемой камеры при заданном разрешении. Для большинства современных камер это 30 FPS. При необходимости, можно более точно указать FPS при публикации. Для этого нормализация ограничений должна быть отключена:
Code Block |
---|
|
session.createStream({
...
disableConstraintsNormalization: true,
constraints: {
video: {
width: 640,
height: 360,
frameRate: { max: 15 }
},
audio: true
}
}).on(STREAM_STATUS.PUBLISHING, function (publishStream) {
...
}).publish(); |
Отметим, что в этом случае Firefox может исключить камеру из списка при запросе доступа к ней, если драйвер камеры при запросе браузером сведений о ней не предоставляет требуемую комбинацию разрешения и FPS. Также Firefox может изменить разрешение публикации, если в сведениях о камере, предоставляемых драйвером, заданному FPS соответствует только одно разрешение.
Публикация стерео звука в браузере
Для публикации стерео звука в браузере битрейт аудио должен быть установлен не ниже 60000 бит/с. Этого можно добиться настройкой параметров кодека Opus на стороне клиента
Code Block |
---|
|
session.createStream({
name: streamName,
display: localVideoremoteVideo,
constraints: {
cacheLocalResources: true,
audio: {
receiveVideo: false,
receiveAudiobitrate: false,64000
videoContentHint: "detail"},
...
}
...
}).publish(); |
или на стороне сервера
Code Block |
---|
|
opus_formats = maxaveragebitrate=64000;stereo=1;sprop-stereo=1; |
...
В этом случае браузер Firefox публикует стерео звук.
Публикация стерео звука в браузерах на основе Chrome
Для публикации стерео звука из Chrome, кроме настройки сервера, необходимы также изменения в коде клиента. В зависимости от реализации клиента, способы публикации будут разными
С использованием Web SDK
При использовании Web SDK, необходимо при публикации указать следующую опцию в ограничениях:
Code Block |
---|
|
session.createStream({
name: streamName,
display: localVideo,
displayconstraints: localVideo,{
cacheLocalResourcesaudio: true,
{
receiveVideostereo: false,true
receiveAudio: false},
videoContentHint: "motion"...
}
...
}).publish(); |
В сборке WebSDK 2.0.204 в пример Media Devices добавлен пример установки опции videoContentHint
Image Removed
Управление FPS в браузере Firefox
...
С использованием Websocket API
Если в проекте используется только Websocket API, необходимо отключить эхоподавление
Code Block |
---|
|
session.createStream({
...
var constraints = {
disableConstraintsNormalization: true,
constraintsaudio: {
video echoCancellation: {false,
widthgoogEchoCancellation: 640,false
},
height: 360, ...
};
...
frameRate: { max: 15 }navigator.getUserMedia(constraints, function (stream) {
},...
}, reject); |
При включенном эхоподавлении Chrome публикует моно звук, даже если в настройках кодека Opus заданы параметры стерео.
Обход блокировки шифрованного UDP трафика
В некоторых случаях шифрованный UDP медиатрафик может блокироваться на стороне провайдера. При этом публикация WebRTC потока с использованием UDP транспорта не будет работать и завершится с ошибкой Failed by RTP activity
. В таких случаях рекомендуется использовать TCP транспорт на стороне клиента
Code Block |
---|
|
session.createStream({
audioname: truestreamName,
display: }
}).on(STREAM_STATUS.PUBLISHING, function (publishStream) {localVideo,
transport: "TCP"
...
}).publish(); |
Отметим, что в этом случае Firefox может исключить камеру из списка при запросе доступа к ней, если драйвер камеры при запросе браузером сведений о ней не предоставляет требуемую комбинацию разрешения и FPS. Также Firefox может изменить разрешение публикации, если в сведениях о камере, предоставляемых драйвером, заданному FPS соответствует только одно разрешениеТакже можно использовать внешний или встроенный TURN сервер либо RTMP или RTSP для публикации потока.
Известные проблемы
1. Если веб-приложение расположено внутри iframe элемента, публикация видеопотока может не пройти.
...