Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

WCS предоставляет возможность захвата медиапотока из файла MP4, расположенного на локальном диске сервера (Video on Demand, VOD). Полученный поток можно воспроизвести, ретранслировать, управлять им, как любым потоком на WCS-сервере. Прежде всего, данная возможность предназначена для воспроизведения записанных ранее трансляций в браузере или мобильном приложении клиента.

Описание

Для захвата VOD из файла в качестве имени потока при вызове функции session.createStream() должна быть указана ссылка на файл в виде:

vod://sample.mp4

где sample.mp4 - имя файла, который должен находиться в каталоге /usr/local/FlashphonerWebCallServer/media/

В случае, если файл с таким именем отсутствует, сервер вернет сообщение StreamStatusEvent FAILED, в поле "info" которого будет указан диагноз "File not found".

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

vod-live://sample.mp4

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

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

  • Контейнер: MP4
  • Видео: H.264
  • Аудио: AAC

Схема работы


  1. Браузер соединяется с сервером по протоколу Websocket и отправляет команду publish.
  2. Браузер захватывает микрофон и камеру и отправляет WebRTC поток H.264 + AAC на сервер с параметром record: true.
  3. WCS-сервер записывает поток в файл.
  4. Браузер останавливает публикацию.
  5. Второй браузер устанавливает соединение по Websocket, создает поток с указанием имени файла и отправляет команду play.
  6. Второй браузер получает WebRTC поток и воспроизводит этот поток на странице.

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

1. Для теста используем веб-приложение Player для воспроизведения файла.

2. Загрузите файл в каталог /usr/local/FlashphonerWebCallServer/media/

3. Откройте веб-приложение Player, укажите в поле Stream имя файла:


4. Нажмите Start. Начнется воспроизведение файла:


5. Нажмите Stop для остановки воспроизведения.

6. Удалите файл из каталог /usr/local/FlashphonerWebCallServer/media/

7. Нажмите Start. Отобразится статус FAILED и сообщение "File not found":

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

Ниже описана последовательность вызовов при использовании:

примера Stream Recording для публикации потока и записи файла

recording.html

recording.js

примера Player для воспроизведения VOD-потока

player.html

player.js


1. Установка соединения с сервером для публикации и записи потока.

Flashphoner.createSession(); code

Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
setStatus(session.status());
//session connected, start playback
publishStream(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus(SESSION_STATUS.DISCONNECTED);
onStopped();
}).on(SESSION_STATUS.FAILED, function(){
setStatus(SESSION_STATUS.FAILED);
onStopped();
});


2. Получение от сервера события, подтверждающего успешное соединение.

ConnectionStatusEvent ESTABLISHED code

Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
setStatus(session.status());
//session connected, start playback
publishStream(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus(SESSION_STATUS.DISCONNECTED);
onStopped();
}).on(SESSION_STATUS.FAILED, function(){
setStatus(SESSION_STATUS.FAILED);
onStopped();
});


3. Публикация потока с указанием признака записи:

stream.publish(); code

session.createStream({
name: streamName,
display: localVideo,
record: true,
receiveVideo: false,
receiveAudio: false
}).on(STREAM_STATUS.PUBLISHING, function(stream) {
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
setStatus(stream.status());
showDownloadLink(stream.getRecordInfo());
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream) {
setStatus(stream.status(), stream.getInfo());
showDownloadLink(stream.getRecordInfo());
onStopped();
}).publish();


4. Получение от сервера события, подтверждающего успешную публикацию потока.

StreamStatusEvent, статус PUBLISHING code

session.createStream({
name: streamName,
display: localVideo,
record: true,
receiveVideo: false,
receiveAudio: false
}).on(STREAM_STATUS.PUBLISHING, function(stream) {
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
setStatus(stream.status());
showDownloadLink(stream.getRecordInfo());
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream) {
setStatus(stream.status(), stream.getInfo());
showDownloadLink(stream.getRecordInfo());
onStopped();
}).publish();


5. Отправка аудио-видео потока по WebRTC

6. Остановка публикации потока.

stream.stop(); code

function onStarted(stream) {
$("#publishBtn").text("Stop").off('click').click(function(){
$(this).prop('disabled', true);
stream.stop();
}).prop('disabled', false);
}

7. Получение от сервера события, подтверждающего остановку публикации потока.

StreamStatusEvent, статус UNPUBLISHED code

session.createStream({
name: streamName,
display: localVideo,
record: true,
receiveVideo: false,
receiveAudio: false
}).on(STREAM_STATUS.PUBLISHING, function(stream) {
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
setStatus(stream.status());
showDownloadLink(stream.getRecordInfo());
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream) {
setStatus(stream.status(), stream.getInfo());
showDownloadLink(stream.getRecordInfo());
onStopped();
}).publish();


8. Установка соединения с сервером для воспроизведения потока.

Flashphoner.createSession(); code

Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
setStatus(session.status());
//session connected, start playback
playStream(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus(SESSION_STATUS.DISCONNECTED);
onStopped();
}).on(SESSION_STATUS.FAILED, function(){
setStatus(SESSION_STATUS.FAILED);
onStopped();
});


9. Получение от сервера события, подтверждающего успешное соединение.

ConnectionStatusEvent ESTABLISHED code

Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
setStatus(session.status());
//session connected, start playback
playStream(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus(SESSION_STATUS.DISCONNECTED);
onStopped();
}).on(SESSION_STATUS.FAILED, function(){
setStatus(SESSION_STATUS.FAILED);
onStopped();
});


10. Воспроизведение потока.

stream.play(); code

if (Flashphoner.getMediaProviders()[0] === "MSE" && mseCutByIFrameOnly) {
options.mediaConnectionConstraints = {
cutByIFrameOnly: mseCutByIFrameOnly
}
}
if (resolution_for_wsplayer) {
options.playWidth = resolution_for_wsplayer.playWidth;
options.playHeight = resolution_for_wsplayer.playHeight;
} else if (resolution) {
options.playWidth = resolution.split("x")[0];
options.playHeight = resolution.split("x")[1];
}
stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
var video = document.getElementById(stream.id());
if (!video.hasListeners) {
video.hasListeners = true;
video.addEventListener('playing', function () {
$("#preloader").hide();
});
video.addEventListener('resize', function (event) {
var streamResolution = stream.videoResolution();
if (Object.keys(streamResolution).length === 0) {
resizeVideo(event.target);
} else {
// Change aspect ratio to prevent video stretching
var ratio = streamResolution.width / streamResolution.height;
var newHeight = Math.floor(options.playWidth / ratio);
resizeVideo(event.target, options.playWidth, newHeight);
}
});
}
}).on(STREAM_STATUS.PLAYING, function(stream) {
$("#preloader").show();
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.STOPPED, function() {
setStatus(STREAM_STATUS.STOPPED);
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream) {
setStatus(STREAM_STATUS.FAILED, stream);
onStopped();
}).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function(stream){
console.log("Not enough bandwidth, consider using lower video resolution or bitrate. Bandwidth " + (Math.round(stream.getNetworkBandwidth() / 1000)) + " bitrate " + (Math.round(stream.getRemoteBitrate() / 1000)));
});
stream.play();


11. Получение от сервера события, подтверждающего успешное воспроизведение потока.

StreamStatusEvent, статус PLAYING code

stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
var video = document.getElementById(stream.id());
if (!video.hasListeners) {
video.hasListeners = true;
video.addEventListener('playing', function () {
$("#preloader").hide();
});
video.addEventListener('resize', function (event) {
var streamResolution = stream.videoResolution();
if (Object.keys(streamResolution).length === 0) {
resizeVideo(event.target);
} else {
// Change aspect ratio to prevent video stretching
var ratio = streamResolution.width / streamResolution.height;
var newHeight = Math.floor(options.playWidth / ratio);
resizeVideo(event.target, options.playWidth, newHeight);
}
});
}
}).on(STREAM_STATUS.PLAYING, function(stream) {
$("#preloader").show();
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.STOPPED, function() {
setStatus(STREAM_STATUS.STOPPED);
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream) {
setStatus(STREAM_STATUS.FAILED, stream);
onStopped();
}).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function(stream){
console.log("Not enough bandwidth, consider using lower video resolution or bitrate. Bandwidth " + (Math.round(stream.getNetworkBandwidth() / 1000)) + " bitrate " + (Math.round(stream.getRemoteBitrate() / 1000)));
});
stream.play();


12. Прием аудио-видео потока по Websocket и воспроизведение по WebRTC

13. Остановка воспроизведения потока.

stream.stop(); code

function onStarted(stream) {
$("#playBtn").text("Stop").off('click').click(function(){
$(this).prop('disabled', true);
stream.stop();
}).prop('disabled', false);
$("#fullScreenBtn").off('click').click(function(){
stream.fullScreen();
}).prop('disabled', false);
$("#volumeControl").slider("enable");
stream.setVolume(currentVolumeValue);
}


14. Получение от сервера события, подтверждающего остановку воспроизведения потока.

StreamStatusEvent, статус STOPPED code

stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
var video = document.getElementById(stream.id());
if (!video.hasListeners) {
video.hasListeners = true;
video.addEventListener('playing', function () {
$("#preloader").hide();
});
video.addEventListener('resize', function (event) {
var streamResolution = stream.videoResolution();
if (Object.keys(streamResolution).length === 0) {
resizeVideo(event.target);
} else {
// Change aspect ratio to prevent video stretching
var ratio = streamResolution.width / streamResolution.height;
var newHeight = Math.floor(options.playWidth / ratio);
resizeVideo(event.target, options.playWidth, newHeight);
}
});
}
}).on(STREAM_STATUS.PLAYING, function(stream) {
$("#preloader").show();
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.STOPPED, function() {
setStatus(STREAM_STATUS.STOPPED);
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream) {
setStatus(STREAM_STATUS.FAILED, stream);
onStopped();
}).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function(stream){
console.log("Not enough bandwidth, consider using lower video resolution or bitrate. Bandwidth " + (Math.round(stream.getNetworkBandwidth() / 1000)) + " bitrate " + (Math.round(stream.getRemoteBitrate() / 1000)));
});
stream.play();
  • No labels