js實現視訊截圖,視訊批量截圖,canvas實現

阿政想暴富發表於2020-12-05

擷取視訊的某一時間的影像並儲存

利用canvas的繪畫能力畫出視訊某一幀的視訊畫面, 獲得到影像之後轉換成base64影像, 再利用a標籤的實現自動儲存到本地

  • html程式碼
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>視訊截圖儲存到本地</title>
</head>

<body>
    <div><button id="btn">開始截圖</button></div>
    <img id="img">
    <a id="a" download="" style="display: none;">去下載</a>
</body>

</html>
  • js程式碼
// 繫結下載
document.getElementById("btn").onclick = function() {
    videoCover("視訊地址", null, 400)
}
/**
 * @param {String} src 視訊連結
 * @param {Number} width 視訊容器播放的寬
 * @param {Number} height 視訊容器播放的高
 * @param {Number} second 需要截圖視訊的幀數, 單位秒
 * @param {Number} bufftime 視訊載入緩衝的時長, 單位秒
 */
function videoCover(src, width, height, second, bufftime) {
    const canvas = document.createElement('canvas'); //  建立canvas 用來截圖
    const video = document.createElement('video'); //  建立video 用來存放被截圖的視訊
    const img = document.getElementById('img') //  用來顯示截圖的圖片效果
    const a = document.getElementById('a') //  用來自動下載圖片儲存到本地
    video.setAttribute('crossOrigin', 'anonymous'); //  支援跨域
    document.body.appendChild(video); //  把視訊插入頁面裡
    video.setAttribute('src', src); //  設定video路徑
    video.style.visibility = "hidden" //  視訊不顯示

    // 監聽視訊播放
    video.onplay = function() {
        // 暫停
        video.pause()
        // 指定播放時間 1代表視訊的第一秒幀 可以浮點數
        video.currentTime = second || 1
        // 設定視訊容器的寬高播放 如果設定一項會自動按照比例生成  這裡是高固定,寬自動
        video.height = height || video.clientHeight;
        // 設定canvas的截圖大小,如果沒給定寬高值會取視訊容器的寬高
        canvas.width = width || video.clientWidth;
        canvas.height = height || video.height;
        /*  
            使用定時器為了視訊跳轉到某一幀的時候視訊進行緩衝,等視訊載入完成之後進行截圖
            如果截圖是黑屏說明視訊未載入完成就開始截圖了
        */
        setTimeout(() => {
            //  使用canvas進行繪畫 視訊畫面
            canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
            // 獲取到base64圖片 png格式
            const IMG_TYPE = "png"
            const b64 = canvas.toDataURL('image/' + IMG_TYPE);
            // 展示到頁面上給img的src賦值
            document.getElementById('img').setAttribute('src', b64);
            // 設定下載圖片地址
            document.getElementById('a').setAttribute('href', b64);
            //  設定下載圖片的名稱
            const filename = "測試圖" + "." + IMG_TYPE
            document.getElementById('a').setAttribute('download', filename);
            //  模擬點選自動下載圖片
            document.getElementById('a').click()
            //  移除視訊容器
            document.body.removeChild(video);
        }, bufftime * 1000 || 3000);
    }
    // 當視訊準備就緒的時候 
    video.onloadeddata = () => {
        //  播放它
        video.play()
    }
}

以上程式碼就完成了單個的視訊截圖了.

  • 如何實現多個視訊批量截圖視訊呢?

使用for迴圈遍歷 呼叫 videoCover 函式, videoCover 需要重寫一下.

先規定需要遍歷視訊截圖的內容

[
    {
        "src":"*******.video", // 視訊下載地址
        "currentTime":5, //需要擷取的視訊幀數,第幾秒
        "filename":"測試1", // 需要下載到本地的檔名
        "filetype":"png" // 下載的圖片型別
    },
    {
        "src":"*******.video", // 視訊下載地址
        "currentTime":5, //需要擷取的視訊幀數,第幾秒
        "filename":"測試1", // 需要下載到本地的檔名
        "filetype":"png" // 下載的圖片型別
    }
]
  • 重寫videoCover 函式

使用promise,async,await 遍歷迴圈截圖下載圖片

/**
* @param {Object} obj 視訊內容物件
* @param {Number} width 視訊容器播放的寬
* @param {Number} height 視訊容器播放的高
* @param {Number} bufftime 視訊載入緩衝的時長, 單位秒
*/
function videoCover(obj, width, height, bufftime) {
    return new Promise((resolve, reject) => {
        const canvas = document.createElement('canvas'); //  建立canvas 用來截圖
        const video = document.createElement('video'); //  建立video 用來存放被截圖的視訊
        const img = document.getElementById('img') //  用來顯示截圖的圖片效果
        const a = document.getElementById('a') //  用來自動下載圖片儲存到本地
        video.setAttribute('crossOrigin', 'anonymous'); //  支援跨域
        document.body.appendChild(video); //  把視訊插入頁面裡
        video.setAttribute('src', obj.src); //  設定video路徑
        video.style.visibility = "hidden" //  視訊不顯示
        // 監聽視訊播放
        video.onplay = function () {
            // 暫停
            video.pause()
            // 指定播放時間 1代表視訊的第一秒幀 可以浮點數
            video.currentTime = obj.currentTime || 1
            // 設定視訊容器的寬高播放 如果設定一項會自動按照比例生成  這裡是高固定,寬自動
            video.height = height || video.clientHeight;
            // 設定canvas的截圖大小,如果沒給定寬高值會取視訊容器的寬高
            canvas.width = width || video.clientWidth;
            canvas.height = height || video.height;
            /*  
                使用定時器為了視訊跳轉到某一幀的時候視訊進行緩衝,等視訊載入完成之後進行截圖
                如果截圖是黑屏說明視訊未載入完成就開始截圖了
            */
            setTimeout(() => {
                //  使用canvas進行繪畫 視訊畫面
                canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
                // 獲取到base64圖片 png格式
                const b64 = canvas.toDataURL('image/' + obj.filetype);
                //  移除視訊容器
                document.body.removeChild(video);
                resolve(b64)
            }, bufftime * 1000 || 3000);
        }
        // 當視訊準備就緒的時候 
        video.onloadeddata = () => {
            //  播放它
            video.play()
        }
    })

}
  • 在寫個迴圈遍歷videoCover 函式
async function start() {
    const DATA = [{
        "src": "http:/****.mp4", // 視訊下載地址
        "currentTime": 5, //需要擷取的視訊幀數,第幾秒
        "filename": "測試1", // 需要下載到本地的檔名
        "filetype": "png" // 下載的圖片型別
    },
    {
        "src": "http:/****.mp4", // 視訊下載地址
        "currentTime": 2, //需要擷取的視訊幀數,第幾秒
        "filename": "測試2", // 需要下載到本地的檔名
        "filetype": "png" // 下載的圖片型別
    }]
    const img = document.getElementById('img')      //  用來顯示截圖的圖片效果
    const a = document.getElementById('a')          //  用來自動下載圖片儲存到本地
    for (let index = 0; index < DATA.length; index++) {
        const element = DATA[index];
        console.log("開始截圖視訊:" + element.src);
        const b64 = await videoCover(element, null, 400, 3)
        // 展示到頁面上給img的src賦值
        img.setAttribute('src', b64);
        // 設定下載圖片地址
        a.setAttribute('href', b64);
        //  設定下載圖片的名稱
        const filename = element.filename + "." + element.filetype
        a.setAttribute('download', filename);
        //  模擬點選自動下載圖片
        a.click()
        console.log("截圖儲存到本地成功:命名<" + filename + ">");
    }
    console.log("所有視訊截圖下載本地完成!");
}
// 繫結下載
document.getElementById("btn").onclick = function () {
    start()
}

然後點選按鈕去截圖,就可以開始批量截圖視訊儲存到本地了.
多個視訊截圖

提示: async/await屬於es7語法,部分低版本瀏覽器暫不支援,需要前往高版本瀏覽器使用!

相關文章