Кстати, пожалуйста, не размещайте ссылки на другие подобные вопросы, потому что я их все видел, и они не помогают. Я работаю над этим в течение 7 часов.
Итак, я пытаюсь захватить видео с веб-камеры (с помощью MediaRecorder) и сохранить его в файл (в wwwroot или базе данных) через контроллер. У меня работает часть захвата видео, но я не уверен, как превратить записанные blob в файл или записываемый объект.
Вот как это работает. Я использую этот скрипт для записи. Это из демо-версии, и она работает отлично, за исключением того факта, что у него есть только возможность загрузки. Часть скрипта, ответственная за загрузку, закомментирована, и под ней я реализовал часть, чтобы попытаться загрузить это видео и сохранить его в папке.
const mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
let mediaRecorder;
let recordedBlobs;
let sourceBuffer;
const errorMsgElement = document.querySelector('span#errorMsg');
const recordedVideo = document.querySelector('video#recorded');
const recordButton = document.querySelector('button#record');
recordButton.addEventListener('click', () => {
if (recordButton.textContent === 'Start Recording') {
startRecording();
} else {
stopRecording();
recordButton.textContent = 'Start Recording';
playButton.disabled = false;
downloadButton.disabled = false;
}
});
const playButton = document.querySelector('button#play');
playButton.addEventListener('click', () => {
const superBuffer = new Blob(recordedBlobs, { type: 'video/webm' });
recordedVideo.src = null;
recordedVideo.srcObject = null;
recordedVideo.src = window.URL.createObjectURL(superBuffer);
recordedVideo.controls = true;
recordedVideo.play();
});
const downloadButton = document.querySelector('button#download');
downloadButton.addEventListener('click', () => {
const blob = new Blob(recordedBlobs, { type: 'video/webm' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'test.webm';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
});
downloadButton.addEventListener('click', () => {
var formData = new FormData();
formData.append('video-filename', fileName);
formData.append('video-blob', recordedBlobs);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/page/upload');
xhr.send(formData);
});
function handleSourceOpen(event) {
console.log('MediaSource opened');
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
console.log('Source buffer: ', sourceBuffer);
}
function handleDataAvailable(event) {
console.log('handleDataAvailable', event);
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
}
function startRecording() {
recordedBlobs = [];
let options = { mimeType: 'video/webm;codecs=vp9' };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = { mimeType: 'video/webm;codecs=vp8' };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = { mimeType: 'video/webm' };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = { mimeType: '' };
}
}
}
try {
mediaRecorder = new MediaRecorder(window.stream, options);
} catch (e) {
console.error('Exception while creating MediaRecorder:', e);
errorMsgElement.innerHTML = `Exception while creating MediaRecorder: ${JSON.stringify(e)}`;
return;
}
console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
recordButton.textContent = 'Stop Recording';
playButton.disabled = true;
downloadButton.disabled = true;
mediaRecorder.onstop = (event) => {
console.log('Recorder stopped: ', event);
console.log('Recorded Blobs: ', recordedBlobs);
};
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10); // collect 10ms of data
console.log('MediaRecorder started', mediaRecorder);
}
function stopRecording() {
mediaRecorder.stop();
}
function handleSuccess(stream) {
recordButton.disabled = false;
console.log('getUserMedia() got stream:', stream);
window.stream = stream;
const gumVideo = document.querySelector('video#gum');
gumVideo.srcObject = stream;
}
async function init(constraints) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
} catch (e) {
console.error('navigator.getUserMedia error:', e);
errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
}
}
document.querySelector('button#start').addEventListener('click', async () => {
const hasEchoCancellation = false;
const constraints = {
audio: {
echoCancellation: { exact: hasEchoCancellation }
},
video: {
width: 1280, height: 720
}
};
console.log('Using media constraints:', constraints);
await init(constraints);
});
Это оригинальная часть:
const downloadButton = document.querySelector('button#download');
//downloadButton.addEventListener('click', () => {
// const blob = new Blob(recordedBlobs, { type: 'video/webm' });
// const url = window.URL.createObjectURL(blob);
// const a = document.createElement('a');
// a.style.display = 'none';
// a.href = url;
// a.download = 'test.webm';
// document.body.appendChild(a);
// a.click();
// setTimeout(() => {
// document.body.removeChild(a);
// window.URL.revokeObjectURL(url);
// }, 100);
//});
и моя попытка:
downloadButton.addEventListener('click', () => {
var formData = new FormData();
formData.append('video-filename', fileName);
formData.append('video-blob', recordedBlobs);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/page/upload');
xhr.send(formData);
});
Это посылает капли рекордера (что, по-видимому, как эти видео сохраняются) на контроллере, который выглядит следующим образом:
[HttpPost]
public async Task<IActionResult> Upload()
{
var form = Request.Form;
var fileName = form["video-filename"];
Debug.WriteLine(form.ToString());
Debug.WriteLine(form["video-filename"]);
Debug.WriteLine(form["video-blob"].ToString());
//var filePath = Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\videos", fileName);
//using (var fileStream = new FileStream(filePath, FileMode.Create))
//{
// await form.CopyToAsync(fileStream);
//}
return View("Upload");
}
Я могу получить доступ к fileName и массиву BLOB-объектов, но я понятия не имею, что делать, чтобы сохранить его в файл. Ваша помощь будет принята с благодарностью.