博客 / 詳情

返回

如何在瀏覽器 console 控制枱中播放視頻?

如何在瀏覽器 console 控制枱中播放視頻?
要實現這個目標,主要涉及到這幾個點:

如何獲取和解析視頻流?
如何在 console 裏播放動態內容?
如何在 console 裏播放彩色內容?
如何連接視頻流和 console?
事實上最後的代碼極其簡單,我們就一步一步簡單講一下

效果

測試地址:yu-tou.github.io/colors-web/…

如何獲取和解析視頻流?
這裏我們用電腦攝像頭捕獲視頻流,然後獲取視頻流每一幀的圖像數據,作為下一步的輸入。

// 捕捉電腦攝像頭的視頻流
const mediaStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
// 創建一個 video 標籤
const video = document.createElement("video");
document.body.appendChild(video);

video.onloadedmetadata = function (e) {
video.play(); // 等攝像頭數據加載完成後,開始播放
};
// video 標籤播放視頻流
video.srcObject = mediaStream;
複製代碼
如何獲取每一幀圖像的數據?創建一個 canvas 畫布,可以將 video 當前的內容繪製到畫布上,然後通過 canvas 的方法即可拿到圖像的像素數據。

const ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;

ctx.drawImage(video, 0, 0, width, height);
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
// imageData 的結構是平鋪的,需要自己去學習下
複製代碼
如何在 console 裏播放動態內容?
視頻每幀的圖像內容我們已經可以拿到了,繼續下一步,如果需要在 console 中完成播放視頻,首先需要能夠一幀一幀繪製內容,但是這個好像是不太現實的,console.log 只能輸出文本。

回想遠古時代,在終端裏大家怎麼播放視頻的?沒錯,用字符畫一幀一幀繪製,連起來不就是動態的視頻了。

當然 chrome dev tool 裏如果每一幀繪製後都調用 console.clear() 清空重繪,體驗不是很好,閃爍會很嚴重,所以我們採用持續輸出的方式繪製,當你停留在 console 的最後的時候,看起來也算是動態內容了。

如何在 console 裏播放彩色內容?
console.log 支持部分 css 特性,可以為輸出的字符串指定簡單的樣式,最基本的支持背景色、字體顏色、下劃線等,甚至支持 background-image、padding 等特性,利用這些特性,甚至可以插入圖片,但是這些特性在不同瀏覽器的 console 中或多或少有些兼容問題,不過要實現字體着色,或者輸出色塊(用背景色),問題不大。

我們在此使用 colors-web 來更方便地輸出彩色內容到控制枱。

這是一個非常方便的庫,可以使用鏈式調用在控制枱快速輸出彩色內容,並且支持諸多特性,無需自己去了解,直接使用對應的方法即可。

如:

import { logger, colors } from "colors-web";
logger(
colors().red().fontsize(48).fontfamily("SignPainter").log("hello"),
colors().white.redBg("hello").linethrough(),
"world",
colors().white.padding(2, 5).underline().lightgrey("芋頭")
);
複製代碼
相信我不解釋,大家也基本理解這些用法,非常簡單和自由,而且支持 typescript。

我們這裏,用 colors-web 輸出色塊:

for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {

if (i * width + j < data.length) {
  const color = `rgb(${data[(i * width + j) * 4 + 0]},${data[(i * width + j) * 4 + 1]},${
    data[(i * width + j) * 4 + 2]
  })`;
  colors()
    .bg(color)
    .color(color)
    .fontfamily(/Chrome/.test(navigator.userAgent) ? "Courier" : "")
    .log("╳");
}

}
}
複製代碼
最終邏輯
最終我將每一幀所有的像素值都轉換成一個 colors 的實例,記錄到數組之後,最終統一調用 logger 即可完成一幀的渲染。

const frameColors = [];
for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {

if (i * width + j < data.length) {
  const color = `rgb(${data[(i * width + j) * 4 + 0]},${data[(i * width + j) * 4 + 1]},${
    data[(i * width + j) * 4 + 2]
  })`;
  frameColors.push(
    colors()
      .bg(color)
      .color(color)
      .fontfamily(/Chrome/.test(navigator.userAgent) ? "Courier" : "")
      .log("╳")
  );
}

}
}
// 繪製,colors() 只是在準備數據結構,logger 才是真正的輸出
logger(...frameColors);
最後
如果你覺得此文對你有一丁點幫助,點個贊。或者可以加入我的開發交流羣:1025263163相互學習,我們會有專業的技術答疑解惑

如果你覺得這篇文章對你有點用的話,麻煩請給我們的開源項目點點star: https://gitee.com/ZhongBangKe...不勝感激 !

user avatar andy-croxall 頭像 heyiming 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.