Создание видео отзывов на JavaScript и PHP
Нажмите кнопку «Старт», чтобы начать запись видео длительностью не более 5 секунд. Вы можете остановить видео, нажав кнопку «Стоп». Кнопка «Скачать» загрузит полученные данные в несжатом виде прямо из браузера. Ниже будет показан блок с видео, загруженное на сервер.
Старт
Предпросмотр
<style>
video {
margin-top: 2px;
border: 1px solid black;
}
.button {
cursor: pointer;
display: block;
width: 160px;
border: 1px solid black;
font-size: 16px;
text-align: center;
padding-top: 2px;
padding-bottom: 4px;
color: white;
background-color: darkgreen;
text-decoration: none;
}
.block {
margin: 10px;
float: left;
width: 160px;
padding: 0;
}
.bottom {
clear: both;
padding-top: 10px;
}
</style>
<div class="block">
<div id="startButton" class="button">Старт</div>
<h2>Предпросмотр</h2>
<video id="preview" width="160" height="120" autoplay muted></video>
</div>
<div class="block">
<div id="stopButton" class="button">Стоп</div>
<h2>Запись</h2>
<video id="recording" width="160" height="120" controls></video>
<a id="downloadButton" class="button"> Скачать </a>
</div>
<div class="bottom">
<pre id="log"></pre>
</div>
<br>
<div id="rec"></div>
<br class="clear">
<script>
let preview = document.getElementById("preview");
let recording = document.getElementById("recording");
let startButton = document.getElementById("startButton");
let stopButton = document.getElementById("stopButton");
let downloadButton = document.getElementById("downloadButton");
let logElement = document.getElementById("log");
let recordingTimeMS = 5000; // максимальный размер видео в миллисекундах
let recorder;
function _log(msg) { logElement.innerHTML += msg + "\n"; }
function wait(delayInMS) {
return new Promise((resolve) => setTimeout(resolve, delayInMS));
}
function startRecording(stream, lengthInMS) {
recorder = new MediaRecorder(stream);
let data = [];
recorder.ondataavailable = (event) => data.push(event.data);
recorder.start();
_log(recorder.state + " в пределах " + lengthInMS / 1000 + " секунд...");
let stopped = new Promise((resolve, reject) => {
recorder.onstop = resolve;
recorder.onerror = (event) => reject(event.name);
});
let recorded = wait(lengthInMS).then( () => recorder.state === "recording" && recorder.stop() );
return Promise.all([stopped, recorded]).then(() => data);
}
function stop(stream) {
stream.getTracks().forEach((track) => track.stop());
}
startButton.addEventListener( "click", ()=> {
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((stream) => {
preview.srcObject = stream;
downloadButton.href = stream;
preview.captureStream = preview.captureStream || preview.mozCaptureStream;
return new Promise((resolve) => (preview.onplaying = resolve));
})
.then(() => startRecording(preview.captureStream(), recordingTimeMS))
.then((recordedChunks) => {
let recordedBlob = new Blob(recordedChunks, { type: "video/webm" });
_log("Успешно записано " + Math.round(recordedBlob.size/1024) + "Kb в формате " + recordedBlob.type);
//stop(preview.srcObject);
// это блок для работы без сервера
recording.src = URL.createObjectURL(recordedBlob); // todo URL.revokeObjectURL(recording.src);
downloadButton.href = recording.src;
downloadButton.download = "RecordedVideo.webm";
// это блок отправки видео на сервер
/* let fd = new FormData();
fd.append('voice', recordedBlob);
sendVoice(fd);*/
})
.catch(_log);
},
false,
);
stopButton.addEventListener( "click", ()=> { stop(preview.srcObject); }, false );
async function sendVoice(form) {
//fetch('video_review.php',{method: 'POST', body: data}).then(function (e) {e.json().then(function (e) { _log('Записал на сервер под именем: ', e.data);}
let promise = await fetch('video_review.php', {
method: 'POST',
body: form});
if (promise.ok) {
let response = await promise.json();
_log('Записал на сервер под именем: '+response.data);
if(response.result==='ERROR') _log('Ошибка: '+response.result.data);
else document.getElementById('rec').insertAdjacentHTML('afterend', '<video controls="controls" style="width:200px;margin:10px;float:left">'+
'<source src="https://htmlweb.ru/log/tmp/'+response.data+'" type="video/webm">'+
'</video><br><a href="?del='+response.data+'" onclick="return confirm(this.title+\'?\')" title="Удалить"><svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#1f1f1f"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z" fill="#e34234"/></svg></a>');
}else{
}
}
</script>
Получение и удаление файла на сервере
if(!empty($_FILES['voice'])) {
$typeFile = explode('/', $_FILES['voice']['type']);
if(empty($typeFile[1])||!in_array($typeFile[1], ['webm','mp4']))die(json_encode(['result' => 'ERROR', 'data' => 'Неверный формат файла '.$_FILES['voice']['type']]));
$fil=date('ymdHi') . '.' . $typeFile[1];
$src = '/log/tmp/' . $fil;
$uploadFile = $_SERVER['DOCUMENT_ROOT'] . $src;
if (move_uploaded_file($_FILES['voice']['tmp_name'], $uploadFile)) {
$response = ['result' => 'OK', 'data' => $fil];
if(!isset($_SESSION[Image::$fieldSession]))$_SESSION[Image::$fieldSession]=[];
$_SESSION[Image::$fieldSession][]=$fil;
} else {
$response = ['result' => 'ERROR', 'data' => 'Не смог сохранить' . $_FILES['voice']['tmp_name'] . ' в ' . $uploadFile];
}
header('Content-Type: application/json');
die(json_encode($response));
}elseif (!empty($_REQUEST['del']) && is_file($fil=$_SERVER['DOCUMENT_ROOT'] . '/log/tmp/'.$_REQUEST['del'])){
unlink($fil);
}
- Исходник https://developer.mozilla.org/ru/docs/Web/API/MediaStream_Recording_API/Recording_a_media_element
- Описание MediaRecorder https://developer.mozilla.org/ru/docs/Web/API/MediaRecorder
- Как сделать превью видео с помощью canvas https://usefulangle.com/post/46/javascript-get-video-thumbnail-image-jpeg-png
.
Прокомментировать/Отблагодарить