Как создать видео с потоковой веб-камеры и холста?

Я пытаюсь создать видео в браузере из другого фрагмента: Слайд: поток с холста Видео: трансляция с веб-камеры

Я просто хочу разрешить пользователю загружать редактирование видео с помощью слайд1 + видео1 + слайд2 + видео2 + слайд3 + видео3.

Вот мой код:

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const webcam = document.getElementById('webcam');
const videoPlayer = document.createElement('video');
videoPlayer.controls = true;
document.body.appendChild(videoPlayer);
const videoWidth = 640;
const videoHeight = 480;
let keepAnimating = true;
const frameRate=30;
// Attempt to get webcam access
function setupWebcam() {
 const constraints = {
        video: {
             frameRate: frameRate,
            width: videoWidth,  
            height: videoHeight 
        }
    };
  navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
      webcam.srcObject = stream;
      webcam.addEventListener('loadedmetadata', () => {
        recordSegments();
        console.info('Webcam feed is now displayed');
      });
    })
    .catch(err => {
      console.error("Error accessing webcam:", err);
      alert('Could not access the webcam. Please ensure permissions are granted and try again.');
    });
}


// Function to continuously draw on the canvas
function animateCanvas(content) {
  if (!keepAnimating) {
    console.info("keepAnimating", keepAnimating);
    return;
  }; // Stop the animation when keepAnimating is false

  ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear previous drawings
  ctx.fillStyle = `rgba(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, 0.5)`;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = '#000';
  ctx.font = '48px serif';
  ctx.fillText(content + ' ' + new Date().toLocaleTimeString(), 50, 100);

  // Request the next frame
  requestAnimationFrame(() => animateCanvas(content));
}


// Initialize recording segments array
const recordedSegments = [];
// Modified startRecording to manage animation
function startRecording(stream, duration = 5000, content) {
  const recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
  const data = [];

  recorder.ondataavailable = e => data.push(e.data);


  // Start animating the canvas
  keepAnimating = true;
  animateCanvas(content);
  recorder.start();
  return new Promise((resolve) => {
    // Automatically stop recording after 'duration' milliseconds
    setTimeout(() => {
      recorder.stop();
      // Stop the animation when recording stops
      keepAnimating = false;
    }, duration);

    recorder.onstop = () => {
      const blob = new Blob(data, { type: 'video/webm' });
      recordedSegments.push(blob);
       keepAnimating = true;
      resolve(blob);
    };
  });
}

// Sequence to record segments
async function recordSegments() {
  // Record canvas with dynamic content
  await startRecording(canvas.captureStream(frameRate), 2000, 'Canvas Draw 1').then(() => console.info('Canvas 1 recorded'));

      await startRecording(webcam.srcObject,3000).then(() => console.info('Webcam 1 recorded'));

          await startRecording(webcam.srcObject).then(() => console.info('Webcam 1 recorded'));
  mergeAndDownloadVideo();
}

function downLoadVideo(blob){
 const url = URL.createObjectURL(blob);

  // Create an anchor element and trigger a download
  const a = document.createElement('a');
  a.style.display = 'none';
  a.href = url;
  a.download = 'merged-video.webm';
  document.body.appendChild(a);
  a.click();

  // Clean up by revoking the Blob URL and removing the anchor element after the download
  setTimeout(() => {
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
  }, 100);
}
function mergeAndDownloadVideo() {
  console.info("recordedSegments length", recordedSegments.length);
  // Create a new Blob from all recorded video segments
  const superBlob = new Blob(recordedSegments, { type: 'video/webm' });
  
  downLoadVideo(superBlob)

  // Create a URL for the superBlob
 
}

// Start the process by setting up the webcam first
setupWebcam();

Найти его можно здесь: https://jsfiddle.net/Sulot/nmqf6wdj/25/

Я не могу создать один «слайд» + видео с веб-камеры + «слайд» + видео с веб-камеры.

Он объединяет только первые 2 сегмента, но не другой. Я попробовал со стороны браузера ffmpeg.

Вам нужно сузить эту проблему. Если все ваши отдельные видеоклипы записываются нормально, то проблема здесь не в 95% кода, а связана только с вашим воспроизведением и переключением, да?

Brad 30.04.2024 05:50

Да, вы, мол, правы на 100%. Однако я не могу понять, в чем проблема. Я удаляю часть «игры» при загрузке. И загрузка не работает. И нет, видеоклип не по отдельности правильный, только первые.

Stefdelec 30.04.2024 11:12

Хорошо, теперь я понимаю, что вы пытаетесь объединить видео из совершенно разных видео? Это не сработает. У вас разные данные трека с холста и веб-камеры, а что нет. Вы не можете просто объединить произвольные фрагменты видео таким образом. Кроме того, то, что выходит из MediaRecorder, не является отдельными частями. Это всего лишь части длинного видеопотока. Есть два способа сделать то, что, как мне кажется, вы хотите сделать... либо взять независимые видеопотоки и выполнить сращивание на стороне сервера, либо просто нарисовать все на холсте и записать холст как один поток.

Brad 30.04.2024 22:03

Есть третий способ — отказаться от MediaRecorder и использовать API веб-кодеков, но он более сложен, чем вам нужно, и все равно не решает вашу первоначальную проблему переключения потоков. Вам все равно придется рисовать все на этом холсте.

Brad 30.04.2024 22:04
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
4
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, я смог сделать то, что хотел, используя MultiStreamsMixer. https://github.com/muaz-kan/MultiStreamsMixer

Другие вопросы по теме