Передавать поток видео с веб-камеры в реальном времени на сервер с сохранением

mxmod

Новичок
Здравствуйте, я реализовал сохранение записи на сервер с веб-камеры по нажатию кнопки(окончание записи). Я не знаю как сделать, чтобы поток видео передавался в реальном времени, т.е к примеру если закрыть окно браузера или непредвиденно прервётся запись, то на сервере всё равно создастся запись, что успело туда передаться.

JavaScript:
navigator.mediaDevices.getUserMedia({video:true, audio:true}).then((stream)=>{
video.srcObject=stream;
video.play();
console.log(stream);
let mediaRecorder=new MediaRecorder(stream);
console.log(mediaRecorder);
document.querySelector("#start").addEventListener("click", function(){
mediaRecorder.start()
});
 
let videoChunk=[];
mediaRecorder.addEventListener("dataavailable",function(event){
videoChunk.push(event.data)
let videoBlob=new Blob(videoChunk, {type:"video/mp4"});
 
});
 
mediaRecorder.addEventListener("stop",function(){
videoBlob=new Blob(videoChunk, {type:"video/mp4"});
console.log(videoBlob)
let videoURL=URL.createObjectURL(videoBlob);
console.log(videoURL);
let video2 = document.createElement('video');
      video2.src = videoURL;
      video2.controls = true;
      video2.autoplay = false;
    document.querySelector("#video2").appendChild(video2);
    document.querySelector("#save").href=videoURL;
document.querySelector("#save").download="record.mp4";
console.log(videoChunk);
let fd=new FormData();
fd.append("voice", videoBlob);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'index2.php', true);
xhr.onload = function(e) {
  console.log('Sent');
};
xhr.send(fd);
xhr.onreadystatechange=function() {
    if (this.readyState==4 && this.status==200) {
        console.log(this.response);
    }
}
    videoChunk = [];
});
     document.querySelector("#stop").addEventListener('click', function(){
         mediaRecorder.stop();
            
});
 
});
PHP:
<?php
$upload="files/video.mp4";
move_uploaded_file($_FILES["voice"]["tmp_name"], $upload);
?>
 

AmdY

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

grigori

( ͡° ͜ʖ ͡°)
Команда форума
php начинает работать после получения всех данных, поэтому move_uploaded_file не годится. Покопайтесь в расширениях, а лучше реализовывать такие вещи на других языках программирования вроде джавы или гоу.
не так: http-протокол расчитан на полную передачу данных запроса, content-length для POST и PUT-запросов обязателен,
любые приложения начинают работать после получения тела запроса, битые запросы http-сервера игнорируют,
и к php это относится только в той мере, что move_uploaded_file() на java надо писать самому

здесь задача - обрабатывать стриминговую передачу, которая нарушает протокол http, для этого надо написать свой http-сервер, а nginx надо переключить в режим обратного proxy, чтобы он не обрабатывал http по стандарту, а проксировал данные как бинарный поток

любой неблокирующий фреймвок без проблем позволит работать с tcp напрямую, и на php это пишется не проще и не сложнее, чем на остальных языках
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
другое дело, что раз этот вопрос задается, проблема явно в постановке задачи, а не в реализации
 

mxmod

Новичок
другое дело, что раз этот вопрос задается, проблема явно в постановке задачи, а не в реализации
Кстати нашёл пример через fopen, но как я понял он будет работать если только трансляция открывается в виде файла в отдельном окне, а надо чтобы в главной странице сайта было...
PHP:
<?php

function flush_buffers(){
    ob_end_flush();
    ob_flush();
    flush();
    ob_start();
}


header('Content-Type: video/mpeg');
$stream = fopen( 'http://localhost:8080/stream.mp2v', "rb" );
#$save = fopen("save.mp4", "w");
while ( ! feof( $stream ) )
{

    $response = fread( $stream, 8192 );
    echo $response;
    #fwrite($save,$stream);
    flush_buffers();
}

fclose( $stream );
fclose($save);
exit();
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
да ничего не надо, просто забрось, ты не понимаешь разницу между запросом и ответом
то у тебя файл передается с камеры на сервер, то ты его пытаешься открыть по fopen когда он уже на сервере
 

ksnk

прохожий
А топикстартеру нужно писать то, что он видит в броузере, или ему нужно совсем автономную запись видео потока на сервер?

Если первое - то в чем проблема? В том, что запись у него идет по вручную нажатой кнопке "стоп", а ему хочется, чтобы отсылалось сразу на сервер. Почему бы не отсылать на сервер сразу, как получены новые данные в "dataavailable" ?
На сервере нужно будет поразбираться, что делать с этими кусочками фильма, склеивать их в большой фильм или просто хранить...
 

mxmod

Новичок
А топикстартеру нужно писать то, что он видит в броузере, или ему нужно совсем автономную запись видео потока на сервер?

Если первое - то в чем проблема? В том, что запись у него идет по вручную нажатой кнопке "стоп", а ему хочется, чтобы отсылалось сразу на сервер. Почему бы не отсылать на сервер сразу, как получены новые данные в "dataavailable" ?
На сервере нужно будет поразбираться, что делать с этими кусочками фильма, склеивать их в большой фильм или просто хранить...
Нужно создать именно автономною непрерывную запись видео на сервер
Я отправляю blob файлы через ajax FormData. Если сервер будет их принимать по каждому событию dataavailable, то там же столько кусочков видео будет. Вот поэтому и хочу узнать, есть ли способ попроще решить проблему на JS и PHP?
 

ksnk

прохожий
есть ли способ попроще решить проблему на JS и PHP?
Сейчас есть большая приемная сторона - броузер и маленькая серверная - "а сохрани ка файл...". Предлагается выкинуть большую и ...?

Вероятно, проще найти готовое решение по тому типу видеопотока, который транслируется.

Если хочется помучится и своими силами - можно пускать headless броузер на сервере c той же страничкой, а он уже сам пусть нажимает на кнопку "стоп" когда ему нужно...
 

mxmod

Новичок
Сейчас есть большая приемная сторона - броузер и маленькая серверная - "а сохрани ка файл...". Предлагается выкинуть большую и ...?

Вероятно, проще найти готовое решение по тому типу видеопотока, который транслируется.

Если хочется помучится и своими силами - можно пускать headless броузер на сервере c той же страничкой, а он уже сам пусть нажимает на кнопку "стоп" когда ему нужно...
А если к примеру через setinterval отправлять массив с медиа данными от dataavailable на сервер, то там возможно будет потом объединить все эти кусочки массива и сгенерировать их них видео?
 

Squats

Новичок
Вы каждый раз хотите формировать и отправлять запрос в реальном времени?
Кажись тут нужно постоянное соединение, пока не отправите Connection: Close например, по завершению когда это потребуется.
Посмотрите как работает RTMP протокол - это уже давно сделали за вас.
Как раз для таки случаев.
 
Сверху