上傳檔案時如何獲取視訊長度
上傳時如何獲取視訊長度
思路
首先,獲取視訊長度,我們通過瀏覽器自帶的API就可以獲取,如下:
<!-- html -->
<video src="xxx.mp4"></video>
<!-- JS -->
const oVideo = document.getElementById('video');
oVideo.duration; // 此屬性就可以拿到時間
此時可以發現,src中只能填入路徑,但是上傳檔案我們只有檔案,所以問題就集中在如何拿到路徑
-
思路一:通常預覽圖片的時候,我們會將檔案轉成
base64
然後賦值給src
,那麼此時視訊是不是可以同理呢.. -
思路二:
URL.createObjectURL()
此方法能建立一個臨時的URL,和此視窗的生命週期繫結,剛好符合
MDN解釋
靜態方法會建立一個 DOMString,其中包含一個表示引數中給出的物件的URL。這個 URL 的生命週期和建立它的視窗中的 document 繫結。這個新的URL 物件表示指定的 File 物件或 Blob 物件。
注意URL.revokeObjectURL() 方法來釋放
- 思路三:既然拿到了file 物件,能不能直接從中獲取資訊
從file物件的屬性中來看 沒有此類資訊, 那麼如何來解決呢?
分析mp4
檔案,總所周知,計算機上所有的檔案都是以2進位制的形式存在,各種不同型別的檔案都是有不同的規則來組織起來的,本質都是0和1,那麼以mp4
Uint8Array、DataView、ArrayBuffer
那麼主要問題就是知道檔案規範...
程式碼實現
- 方法一 (檔案過大就會慢)
function change (e) { const file = oFile.files[0]; let reader = new FileReader(); const oVideo = document.createElement('video'); const aBlob = new Blob([file],{type:'video/mp4'}) reader.onload = function(result) { // console.log(reader.result); oVideo.src = reader.result } reader.readAsDataURL(aBlob); // oVideo.preload = 'metadata'; oVideo.onloadedmetadata = function (e) { // 視訊總長度,秒為單位 console.log('....', oVideo.duration); } // document.body.appendChild(oVideo); }
- 方法二
const file = oFile.files[0];
const oVideo = document.createElement('video');
// oVideo.preload = 'metadata';
oVideo.onloadedmetadata = function (e) {
// 視訊總長度,秒為單位
console.log( '....', oVideo.duration);
}
oVideo.src = URL.createObjectURL(file)
注意:preload="metadata"
> 提示儘管作者認為使用者不需要檢視該視訊,不過抓取元資料(比如:長度)還是很合理的。
上述兩種方式都是借用Video
元素提供的API和onloadedmetadata
事件實現
- 方法三
function change2 () {
const file = oFile.files[0];
console.log(file)
file.arrayBuffer().then(res => {
console.log(res)
const ui8 = new Uint8Array(res);
const view = new DataView(res)
console.log(ui8)
console.log(view)
analysis(view);
})
}
function analysis (view) {
// 下標
let idx = 0;
for(; idx < view.byteLength ;) {
boxHeader = analysisHeaderBox(view, idx);
console.log(boxHeader, '...')
// 找到moov 處理
if (boxHeader.type === 'moov') {
// 跳過頭
const son = view.buffer.slice(idx + 8, view.byteLength);
analysis(new DataView(son));
}
if (boxHeader.type === 'mvhd') {
// 跳過頭
const son = view.buffer.slice(idx + 8, boxHeader.size);
analysisMvhdBox(new DataView(son));
}
// 偏移
idx += boxHeader.size;
}
}
// box header 中的 size 和 type
function analysisHeaderBox (view, offset) {
const size = view.getUint32(offset);
offset += 4;
let type = analysisBoxType(
view.getUint8(offset),
view.getUint8(offset + 1),
view.getUint8(offset + 2),
view.getUint8(offset + 3)
);
return {
size,
type
};
}
// 根據碼點獲取字串
function analysisBoxType () {
let str = '';
for(var i = 0; i < arguments.length; i++) {
str += String.fromCharCode(arguments[i]);
}
return str;
}
function analysisMvhdBox (view) {
console.log(view, '...')
const timescale = view.getUint32(12);
const duration = view.getUint32(16);
console.log(timescale, duration, duration/timescale, '...')
}
擴充套件
通過第三種方式,有以下好處
-
可解析不同的檔案型別,可以獲取檔案內容中的資訊
-
並且不依賴於
BOM
環境 即使在node
環境下也是能使用。 -
就算沒有後綴或者字尾錯誤也可以判斷出來檔案是不是MAP4或其他型別
參考
參考:
https://blog.csdn.net/w5025/article/details/123097108
http://www.360doc.com/content/20/0902/20/49586_933661079.shtml