javascript 读取视频的元数据,如评论、作者等

soat7uwm  于 2023-09-29  发布在  Java
关注(0)|答案(1)|浏览(134)

我用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>
wj8zmpe1

wj8zmpe11#

  • “我在一个包含内容的子框中找到,但它也包含其他信息”*
    (1)了解您的子盒.data输入:

假设这条线: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

将上述字节值粘贴到十六进制编辑器中,以查看解码为文本String的字节。
PS:您可以使用.toString(16)检查任何字节的值(十六进制):

alert("byte value is: " + "0x" + subbox_data[0].toString(16) );

(2)将字节解码为文本,并从中提取Object:

您的输出字符串(来自bytes/data)带有引号,这是不允许的。

Not Allowed : var myStr = "this is a "quote" inside text"
Allowed     : var myStr = "this is a \"quote\" inside text"

必须对内部引号进行转义,方法是在每个引号前面添加一个反斜杠\
不使用decoder.decode(subbox.data),您可以使用以下命令提取嵌入的Object

<!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>

其中 “create Object from text that describes an Object” 的意思是:

var myText = "{ ... }"; //# such String can be converted into an { } Object

相关问题