【问题标题】:Is it possible to rotate video chunks in javascript?是否可以在javascript中旋转视频块?
【发布时间】:2022-01-07 21:07:19
【问题描述】:

我正在尝试旋转视频标签并将其置于“画中画”模式,

我知道我们可以使用 transform: rotateY(180deg) 来旋转视频,但 css 不会应用于“pip”模式的视频。

所以我想如果我们可以旋转它的块然后在“pip”模式下调用它

这里是代码,有什么建议请...

const cameraRecording = async function(micStatus){
    try{
        const stream = await navigator.mediaDevices.getUserMedia({
            video : true, 
            audio: micStatus ? false : true
        });
        cameraRecElem.srcObject = stream;
        record(stream, true);
    }
    catch(err){
        showError('Error accessing camera or microphone');
    }
};
const record = function(stream, pipStatus, stream2){

    recorder = new MediaRecorder(stream);

    recorder.addEventListener('start', (e) =>{
        chunks = [];
        if(pipStatus) cameraRecElem.requestPictureInPicture() && (cameraRecElem.style.opacity="0");
    });

    recorder.addEventListener('dataavailable', (e) =>{
        chunks.push(e.data);
    });

    recorder.addEventListener('stop', (e) =>{
        stream.getTracks().forEach(track => track.stop());
        if(stream2) stream2.getTracks().forEach(track => track.stop());
        clearInterval(counting);
        setLink(chunks);
        if(pipStatus) document.exitPictureInPicture();
    });

    startCountDown();
    recorder.start();
}

【问题讨论】:

    标签: javascript video chunks mediadevices picture-in-picture


    【解决方案1】:

    为此,我们需要遍历一个 HTML 画布元素,在那里进行镜像并使用从该画布捕获的流。

    新的VideoCodecsMediaStream Insertable API 在以高性能方式从 MediaStream 抓取帧的过程中提供了很大帮助,但不幸的是,显然没有简单的方法来镜像帧并在不绘制的情况下生成新的 MediaStream画布上的框架。

    对于不支持 WebCodecs API 的浏览器,我们必须通过一个 HTML 视频元素,它将播放 MediaStream 并在画布上绘制该视频元素。

    这是我认为最有效的方法:

    document.querySelector("button").onclick = (evt) => {
      evt.currentTarget.remove();
      const stream = getCanvasStream();
      const mirrored = mirrorStream(stream);
      document.querySelector("video.default").srcObject = stream;
      document.querySelector("video.mirrored").srcObject = mirrored;
    };
    
    function mirrorStream(stream) {
      const canvas = document.createElement("canvas");
      Object.assign(canvas, { width: 0, height: 0 });
      const ctx = canvas.getContext("2d");
      const track = stream.getVideoTracks()[0];
      const drawOnCanvas = (image, width, height) => {
        // MediaStream's video size may change over time
        if (canvas.width !== width || canvas.height !== height) {
          canvas.width = width;
          canvas.height = height;
          ctx.setTransform(-1, 0, 0, 1, width, 0);
        }
        ctx.clearRect(0, 0, width, height);
        ctx.drawImage(image, 0, 0);
      };
      // the MediaStreamTrackProcessor API is available, we use it
      if (window.MediaStreamTrackProcessor) {
        const processor = new MediaStreamTrackProcessor(track);
        const reader = processor.readable.getReader();
        reader.read().then(function readChunk({ done, value }) {
          const { displayWidth, displayHeight } = value;
          drawOnCanvas(value, displayWidth, displayHeight);
          value.close(); // close the VideoFrame when we're done with it
          if (!done) {
            reader.read().then(readChunk);
          }
        });
      } else {
        const vid = document.createElement("video");
        vid.srcObject = stream;
        // in case requestVideoFrameCallback is available, we use it
        // otherwise we fallback on rAF
        const scheduler = vid.requestVideoFrameCallback ?
            (cb) => vid.requestVideoFrameCallback(cb) : requestAnimationFrame;
        const draw = () => {
          const { videoWidth, videoHeight } = vid;
          drawOnCanvas(vid, videoWidth, videoHeight);
          scheduler(draw);
        };
        vid.play().then(draw);
      }
      return canvas.captureStream();
    }
    
    // StackSnippet only:
    // because StackSnippet don't allow the use of gUM
    // we return a MediaStream from a simple <canvas> anim
    function getCanvasStream() {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d");
      ctx.font = "30px sans-serif";
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      function anim() {
        ctx.fillStyle = "white";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "black";
        ctx.fillText(new Date().toTimeString().split(" ")[0], canvas.width / 2, canvas.height / 2);
        requestAnimationFrame(anim);
      }
      anim();
      return canvas.captureStream();
    }
    video { width: calc(50vw - 10px); border: 1px solid; }
    <button>begin</button><br>
    <video autoplay controls class="default">
    </video><video autoplay controls class="mirrored">
    </video>

    作为JSFiddle 使用getUserMedia()


    请注意,如果您确实想要垂直镜像视频,那么我们可以在没有画布的情况下使用 createImageBitmap(VideoFrame, { imageOrientation: "flipY" })MediaStreamTrackGenerator 来实现,但这种方式无法进行水平镜像。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多