【问题标题】:How to reduce the length of a video using JavaScript? [closed]如何使用 JavaScript 减少视频的长度? [关闭]
【发布时间】:2016-12-12 21:25:20
【问题描述】:

我正在尝试从头或尾修剪浏览器中视频的长度。我目前拥有的是一个使用 MediaRecorder API 录制的 MediaStream,我使用它在录制结束时生成一个 Blob,类型设置为“video/mp4”。这很好用,我可以播放视频,但是我想要一种在开始或结束时修剪视频的方法。

在对 MediaStream API 进行进一步调查后,我发现了 SourceBuffer 对象,您可以从 MediaStreamTrack 获取该对象并使用它来删除时间片,这正是我想要的。但是我不确定如何从视频(blob)中获取 MediaStreamTrack,因为 video.srcObject 属性返回 null。

【问题讨论】:

  • 您是要删除部分视频以播放编辑后的视频,还是提供编辑后的视频以供下载?
  • 有趣的问题。这家伙提到媒体片段是一种可能的解决方案。 stackoverflow.com/a/16992434/1567255我自己没试过。
  • @guest271314 both...Kosch 嗯,这似乎是一种只在特定时间部分播放视频的方法(这是我想要的一部分),但不能真正修剪文件本身,谢谢不过。
  • @naughtyboy "我目前拥有的是一个使用 MediaRecorder API 录制的 MediaStream,我使用它在录制结束时生成一个 Blob,类型设置为 'video/ mp4'" 你能在问题中加入javascript 吗?
  • <video> src 是否在getUserMedia() 成功回调处理程序中设置为stream

标签: javascript html dom browser html5-video


【解决方案1】:

我正在尝试在浏览器中修剪视频的长度,从 无论是开头还是结尾。

您可以使用Array.prototype.slice() 以一秒1000ms 的数据块或其他时间范围删除包含在MediaRecorder dataavailable 事件中的数组的包含blob 的数组末尾的段。其中MediaRecorder.start()用参数1000调用,将每个记录的Blob设置为记录数据的1000ms

方法使用 https://github.com/samdutton/simpl/tree/gh-pages/mediarecorder 的修改版本。添加了<input type="number"> 元素以设置从录制的视频中删除1s 的块,以便使用.slice() 进行播放和下载

html

<video id="gum" autoplay muted controls></video>
<video id="recorded" autoplay controls></video>

<div>
  <button id="record">Start Recording</button><label for="record"></label><br>
  <span>Seconds of recorded video to play (min 1):</span><input min="1" type="number" disabled />
  <button id="play" disabled>Play</button>
  <span>Seconds of recorded video to download (min 1):</span><input min="1" type="number" disabled /><button id="download" disabled>Download</button>
</div>

javascript

'use strict';

/* globals MediaRecorder */

// This code is adapted from
// https://rawgit.com/Miguelao/demos/master/mediarecorder.html

'use strict';

/* globals MediaRecorder */

// This code is adapted from
// https://rawgit.com/Miguelao/demos/master/mediarecorder.html

var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
var mediaRecorder;
var recordedBlobs;
var sourceBuffer;
var gumVideo = document.querySelector('video#gum');
var recordedVideo = document.querySelector('video#recorded');
var input = document.querySelectorAll("input[type=number]");
recordedVideo.ontimeupdate = function(e) {
  console.log("recorded video currentTime:", e.target.currentTime)
}
gumVideo.onprogress = function(e) {
  // console.log("getUserMedia video currentTime:", e.target.currentTime)
}
var recordButton = document.querySelector('button#record');
var playButton = document.querySelector('button#play');
var downloadButton = document.querySelector('button#download');
recordButton.onclick = toggleRecording;
playButton.onclick = play;
downloadButton.onclick = download;

var currentTimes = [];
recordButton.nextElementSibling.innerHTML = "recorded video " 
                                            + currentTimes.length 
                                            + "s";
// window.isSecureContext could be used for Chrome
var isSecureOrigin = location.protocol === 'https:' ||
  location.host === 'localhost';
if (!isSecureOrigin) {
  alert('getUserMedia() must be run from a secure origin: HTTPS or localhost.' +
    '\n\nChanging protocol to HTTPS');
  location.protocol = 'HTTPS';
}

// Use old-style gUM to avoid requirement to enable the
// Enable experimental Web Platform features flag in Chrome 49

navigator.getUserMedia = navigator.getUserMedia ||
  navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

var constraints = {
  audio: true,
  video: true
};

navigator.getUserMedia(constraints, successCallback, errorCallback);

function successCallback(stream) {
  console.log('getUserMedia() got stream: ', stream);
  window.stream = stream;
  if (window.URL) {
    gumVideo.src = window.URL.createObjectURL(stream);
  } else {
    gumVideo.src = stream;
  }
}

function errorCallback(error) {
  console.log('navigator.getUserMedia error: ', error);
}

// navigator.mediaDevices.getUserMedia(constraints)
// .then(function(stream) {
//   console.log('getUserMedia() got stream: ', stream);
//   window.stream = stream; // make available to browser console
//   if (window.URL) {
//     gumVideo.src = window.URL.createObjectURL(stream);
//   } else {
//     gumVideo.src = stream;
//   }
// }).catch(function(error) {
//   console.log('navigator.getUserMedia error: ', error);
// });

function handleSourceOpen(event) {
  console.log('MediaSource opened');
  sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
  console.log('Source buffer: ', sourceBuffer);
}

function handleDataAvailable(event) {
  if (event.data && event.data.size > 0) {
    currentTimes.push(gumVideo.currentTime);
    recordedBlobs.push(event.data);
    recordButton.nextElementSibling.innerHTML = "recorded video " 
                                                + recordedBlobs.length 
                                                + "s";
  }
}

function handleStop(event) {
  console.log('Recorder stopped: ', event);
  console.log("recorded times from getUserMedia video:", currentTimes);
}

function toggleRecording() {
  if (recordButton.textContent === 'Start Recording') {
    startRecording();
  } else {
    stopRecording();
    recordButton.textContent = 'Start Recording';
    playButton.disabled = false;
    downloadButton.disabled = false;
  }
}

// The nested try blocks will be simplified when Chrome 47 moves to Stable
function startRecording() {
  var options = {
    mimeType: 'video/webm',
    bitsPerSecond: 100000
  };
  recordedBlobs = [];
  currentTimes = [];
  for (var i = 0; i < input.length; i++) {
    input[i].setAttribute("max", 1);
    input[i].setAttribute("disabled", "disabled");
  }
  playButton.disabled = true;
  downloadButton.disabled = true;
  try {
    mediaRecorder = new MediaRecorder(window.stream, options);
  } catch (e0) {
    console.log('Unable to create MediaRecorder with options Object: ', e0);
    try {
      options = {
        mimeType: 'video/webm,codecs=vp9',
        bitsPerSecond: 100000
      };
      mediaRecorder = new MediaRecorder(window.stream, options);
    } catch (e1) {
      console.log('Unable to create MediaRecorder with options Object: ', e1);
      try {
        options = 'video/vp8'; // Chrome 47
        mediaRecorder = new MediaRecorder(window.stream, options);
      } catch (e2) {
        alert('MediaRecorder is not supported by this browser.\n\n' +
          'Try Firefox 29 or later, or Chrome 47 or later,'
          + ' with Enable experimental Web Platform features enabled '
          + ' from chrome://flags.');
        console.error('Exception while creating MediaRecorder:', e2);
        return;
      }
    }
  }
  console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
  recordButton.textContent = 'Stop Recording';
  playButton.disabled = true;
  downloadButton.disabled = true;
  mediaRecorder.onstop = handleStop;
  mediaRecorder.ondataavailable = handleDataAvailable;
  mediaRecorder.start(1000); // collect 1000ms of data
  console.log('MediaRecorder started', mediaRecorder);
}

function stopRecording() {
  mediaRecorder.stop();
  for (var i = 0; i < input.length; i++) {
    input[i].setAttribute("max", recordedBlobs.length);
    input[i].removeAttribute("disabled");
  }
  console.log('Recorded Blobs: ', recordedBlobs);
  recordedVideo.controls = true;
}

function play() {
  console.log(`playing ${input[0].value}s of getUserMedia video` 
             + `recorded by MediaRecorder from time ranges`
             , currentTimes.slice(0, input[0].value));
  // slice `input[0].value` amount, in seconds, from end of recorded video
  // for playback
  var file = recordedBlobs.slice(0, input[0].value);
  var superBuffer = new Blob(file, {
    type: 'video/webm'
  });
  recordedVideo.src = window.URL.createObjectURL(superBuffer);
}

function download() {
    // slice `input[1].value` amount, in seconds, from end of recorded video
    // for download
  var file = recordedBlobs.slice(0, input[1].value);
  var blob = new Blob(file, {
    type: 'video/webm'
  });
  var url = window.URL.createObjectURL(blob);
  var a = document.createElement('a');
  a.style.display = 'none';
  a.href = url;
  a.download = 'test.webm';
  document.body.appendChild(a);
  a.click();
  setTimeout(function() {
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
  }, 100);
}

plnkrhttps://plnkr.co/edit/LxuV5jMX0RZtDxOxT1qa?p=preview

【讨论】:

  • 这是好东西,我的目的是记录流,将 blob 编码为视频,然后操作该视频。我也会让它在用户调整视频长度的同时播放,但这是我最终可能不得不采取的方法。
  • MediaRecorder 在 safari 上不工作
  • @UmeshPatadiya 好的。不确定这与问题有什么关系?
  • 因为您使用 MediaRecorder() 在上面的 sn-p 中录制视频。它正在 chrome 和 mozilla 上运行,你能建议一些解决方案吗?
  • @UmeshPatadiya 没试过 Safari。
猜你喜欢
  • 1970-01-01
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多