js獲取視頻編碼格式信息


遇到問題

在開發中,測試反饋了一個問題,就是在前端上傳視頻后,視頻無法回顯,顯示黑屏。
於是我要來了測試上傳的視頻,看了下后綴名是.mp4, 用vlc打開播放正常,於是我開始了爬坑之旅。

查找原因

因為后綴名和播放都是正常的,先考慮是不是視頻編碼格式問題。
首先查看MDN文檔,查看html支持的視頻格式,了解到支持的視頻后綴有如下: mp4, webm, ogg,那我們的mp4的視頻類型應該沒有問題的。
那就開始看看視頻編碼格式問題,查看視頻編碼的方法我們就用vlc打開視頻:

可以看到,顯示的codec是mp4v:

為了驗證是不是編碼格式的問題,用錄屏軟件和手機分別拍攝了一些視頻做了測試,測試結果如下:

視頻格式 視頻編碼信息(VLC) 網頁能否正常播放
ev錄制mp4 H264-MPEG-4 AVC(part10 avc1) 正常
ev錄制avi MPEG-4 Video(FMP4) 異常
ev錄制flv Flash-Video (FLV1) 異常
ev錄制wmv MS-MPEG-4-Video v3(MP43) 異常
qq桌面端錄制 MPEG-4 Video(MP4V) 異常
qq手機端錄制 H264-MPEG-4 AVC(part10 avc1) 正常
tim錄制 H264-MPEG-4 AVC(part10 avc1) 正常
微信錄制 H264-MPEG-4 AVC(part10 avc1) 正常

根據上述結果可以看到,編碼格式(codec)和文件類型(type,后綴名)會導致視頻無法正常播放。

備注:
ev是windows下的一款錄屏軟件,測試提供的視頻就是用qq桌面端功能錄制的視頻。

解決問題

目前前端操作,獲取文件類型倒是比較簡單,一般傳輸圖片、文本等等都是根據file.type和file.name來判斷是否允許上傳。

但是我們這里只獲取name和type也無法判斷,我們上傳的視頻能否正常播放了。我找了很久的之后,發現了github上大神的寫的一個框架 mp4box.js 可以幫助我們解決這個問題。

mp4box

  1. 安裝

npm i mp4box -S

  1. 導入

import MP4Box from 'mp4box'

  1. 校驗代碼
async videoBeforeUpload(file) {
    const isVideo = file.type === 'video/mp4' || file.type === 'video/ogg' || file.type === 'video/webm';
    const isLt30M = file.size / 1024 / 1024 < 30;
    if (!isVideo) {
        this.$message.warning('請上傳正確格式的視頻!');
        return Promise.reject()
    } else {
        if (!isLt30M) {
             this.$message.warning('上傳視頻文件大小不能超過 30MB!');
             return Promise.reject()
        }
    }

       // 正確的視頻后綴會有mime信息
    let result = await this.checkVideoCode(file)
    let valid = this.getCodecValid(result.mime)
    if (!valid) {
        this.$message.error('請上傳正確的視頻編碼格式')
        return Promise.reject()
    }
},

async checkVideoCode(file) {
    return new Promise((resolve, reject) => {
        const mp4boxFile = MP4Box.createFile();
        const reader = new FileReader();
        reader.readAsArrayBuffer(file);
        reader.onload = function (e) {
            const arrayBuffer = e.target.result;
            arrayBuffer.fileStart = 0;
            mp4boxFile.appendBuffer(arrayBuffer);
        };
        mp4boxFile.onReady = function (info) {
            resolve(info)
        };
        mp4boxFile.onError = function (info) {
            reject(info)
        };
    })
},

getCodecValid(str) {
    let arr = str.split(';')
    return !!(arr[1].includes('mp4a') || arr[1].includes('avc1'));
},

因為我是用了elementUI框架的組件,所以返回的值都是promise類型,大家自行修改為return false 就行了。因為判斷codec 我感覺比較復雜(我懶),所以我用了和類型判斷和getCodecValid 簡單的判斷了一下編碼格式。
通過這兩種方式,我們可以獲取到不能播放的視頻格式了。接下來的處理大家各取所需,可以讓用戶繼續傳,但是沒辦法觀看,讓后端轉碼。或者直接攔截,不讓用戶傳。或者提示,你傳了可以,網頁觀看不了,自己下載下來觀看。

其他框架

在發現和解決問題的過程中,我發現了幾個不錯的視頻組件和轉碼框架。

  1. bilibili的flv格式視頻播放解決方案:flv.js
  2. 視頻播放組件:Mui Player
  3. 常用的視頻處理庫:video.js

補充測試視頻codec信息

視頻格式 視頻編碼信息(VLC) codec信息(MP4BOX) 網頁能否正常播放
ev錄制mp4 H264-MPEG-4 AVC(part10 avc1) video/mp4; codecs="avc1.42c028"; profiles="isom,iso2,avc1,mp41" 正常
ev錄制avi MPEG-4 Video(FMP4) null 異常
ev錄制flv Flash-Video (FLV1) null 異常
ev錄制wmv MS-MPEG-4-Video v3(MP43) null 異常
qq桌面端錄制 MPEG-4 Video(MP4V) application/mp4; codecs="mp4v"; profiles="isom,iso2,mp41" 異常
qq手機端錄制 H264-MPEG-4 AVC(part10 avc1) video/mp4; codecs="avc1.640020,mp4a.40.2"; profiles="isom,iso2,avc1,mp41" 正常
tim錄制 H264-MPEG-4 AVC(part10 avc1) video/mp4; codecs="avc1.64001f,mp4a.40.2"; profiles="isom,iso2,avc1,mp41" 正常
微信錄制 H264-MPEG-4 AVC(part10 avc1) video/mp4; codecs="mp4a.40.2,avc1.64001f"; profiles="mp42,isom" 正常

參考

  1. 使用 JS 獲取視頻 Codec
  2. MDN上關於video的基礎使用
  3. MDN上視頻內容和音頻
  4. MDN上HTML的媒體支持:audio和video元素


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM