我有一个使用 mp4box.js 阅读的视频,我想在浏览器中获取该视频的元数据,例如评论、作者等(我最感兴趣的是评论,您可以轻松添加它们使用 Ctrl-I 快捷键添加到 VLC 中的视频)。我怎么能做到这一点?
现在我在互联网上找不到任何方向。目前,我只能将
https://gpac.github.io/mp4box.js/test/filereader.html中的
moov > udta > meta > ilst
块的大小与我的评论的大小相关联,但二进制内容并不真正匹配所以我想还有另一个解析步骤,我不确定如何获取该块,然后如何解析它,对于这样一个简单的任务来说,这感觉像是一个非常复杂的解决方案。
正如评论中所解释的,
mp4boxFile.onReady
不提供用户元数据:
但是如果我手动阅读该框
udta
,那么我会获得更多信息。不知何故,我发现里面有一个包含内容的子框,但它也包含其他信息,所以我需要知道该框的编码才能读取它:
--> "hdlr" --> "mdir" --> "appl" --> "ilst" --> ©cmt.data:
Hey. I am a comment that I'd like to print in the browser.
I might have json structure inside like ("Hey": [1,2.3]).
R (or byte val: 0x52)
©nam
J (or byte val: 0x4A)
.dataBBH gravitational lensing of gw150914_comment_from_vlc.mp4%
--> "@too" data: Lavf58.76.108
--> "free"
这是我正在使用的代码:
<!DOCTYPE html>
<html>
<head>
<title>MP4 Metadata Extraction</title>
</head>
<body>
<input type="file" id="fileInput" accept=".mp4">
<div id="metadataDisplay"></div>
<script src="https://gpac.github.io/mp4box.js/dist/mp4box.all.js"></script>
<script>
document.getElementById("fileInput").addEventListener("change", function (e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function (e) {
const arrayBuffer = e.target.result;
// Initialize mp4box
const mp4boxFile = MP4Box.createFile();
mp4boxFile.onReady = (info) => {
console.log("READY");
console.log(info);
};
mp4boxFile.onError = () => {
console.log("Error");
};
// Create a Blob from the ArrayBuffer
/* const blob = new Blob([arrayBuffer]);
*/
console.log("created blob");
// Read the Blob using mp4box
arrayBuffer.fileStart = 0;
mp4boxFile.appendBuffer(arrayBuffer);
// Get metadata
const udtaBoxes = mp4boxFile.getBoxes("udta");
const decoder = new TextDecoder('utf-8');
udtaBoxes.forEach((box) => {
console.log("Box ", box);
box.boxes.forEach((subbox) => {
console.log("Subbox", subbox);
if (subbox.data) {
console.log(decoder.decode(subbox.data));
}
});
});
};
reader.readAsArrayBuffer(file);
}
});
</script>
</body>
</html>
假设这一行:
console.log( decoder.decode(subbox.data) );
为您提供以下示例文本:
Hey. I am a comment that I'd like to print in the browser. I might have json structure inside like {"Hey": [10,50,300]}.
那么这意味着您的
subbox
变量的 .data
保存这些字节值(以十六进制格式编写):
48 65 79 2E 20 49 20 61 6D 20 61 20 63 6F 6D 6D 65 6E 74 20 74 68 61 74 20 49 27 64 20 6C 69 6B 65 20 74 6F 20 70 72 69 6E 74 20 69 6E 20 74 68 65 20 62 72 6F 77 73 65 72 2E 20 49 20 6D 69 67 68 74 20 68 61 76 65 20 6A 73 6F 6E 20 73 74 72 75 63 74 75 72 65 20 69 6E 73 69 64 65 20 6C 69 6B 65 20 7B 22 48 65 79 22 3A 20 5B 31 30 2C 35 30 2C 33 30 30 5D 7D 2E
将上述字节值粘贴到十六进制编辑器中以查看解码为文本字符串的字节。
PS:您可以使用
.toString(16)
: 检查任何字节的值(十六进制)
alert("byte value is: " + "0x" + subbox_data[0].toString(16) );
(2) 将字节解码为文本并从中提取对象:
您的输出字符串(来自字节/数据)带有引号,这是不允许的。
Not Allowed : var myStr = "this is a "quote" inside text"
Allowed : var myStr = "this is a \"quote\" inside text"
您必须通过在每个引号前面添加反斜杠\
来
转义内部引号。
您可以使用以下方法
提取嵌入的对象,而不是使用
decoder.decode(subbox.data)
:
<!DOCTYPE html>
<html>
<body>
<script>
//# hold each byte value after converting it into a String character
var bytes_str = "";
//# Array to recreate your input: subbox.data ...
var subbox_data = [ 0x48, 0x65, 0x79, 0x2E, 0x20, 0x49, 0x20, 0x61, 0x6D, 0x20, 0x61, 0x20, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x27, 0x64, 0x20, 0x6C, 0x69, 0x6B, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x72, 0x2E, 0x20, 0x49, 0x20, 0x6D, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x6A, 0x73, 0x6F, 0x6E, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x73, 0x69, 0x64, 0x65, 0x20, 0x6C, 0x69, 0x6B, 0x65, 0x20, 0x7B, 0x22, 0x48, 0x65, 0x79, 0x22, 0x3A, 0x20, 0x5B, 0x31, 0x30, 0x2C, 0x35, 0x30, 0x2C, 0x33, 0x30, 0x30, 0x5D, 0x7D, 0x2E ];
for (let i = 0; i < subbox_data.length; i++)
{
//# replace any " (ie: quote_mark) with a \" (ie: back_slash + quote_mark)
if( subbox_data[i] == 0x22 ) { bytes_str += ( "\"" ) }
//# else use the given String value
else { bytes_str += String.fromCharCode( subbox_data[i] ) }
}
alert("subbox_data text:" + "\n" + bytes_str );
var str_a = ( bytes_str.indexOf("{") - 1 );
var str_b = ( bytes_str.indexOf("}") + 1 );
var extracted_text_for_obj = bytes_str.slice( str_a, str_b );
alert("extracted text (makes new Object):" + "\n" + extracted_text_for_obj);
//# create Object from text that describes an Object setup
const obj_from_text = JSON.parse( extracted_text_for_obj );
//# object has one entry with label "Hey" which is a pointer for an Array
alert(
"new Object has these following entries/keys: " + Object.keys( obj_from_text ) + "\n" +
"entries/keys: Hey contains Array of length: " + (obj_from_text.Hey.length) + "\n" +
"Array[2] at this path... Object.Hey is: " + obj_from_text.Hey[2]
);
</script>
</body>
</html>
其中 “从描述对象的文本创建对象” 的意思类似于:
var myText = "{ ... }"; //# such String can be converted into an { } Object