上传前如何获取视频的元数据(长度)?

Posted

技术标签:

【中文标题】上传前如何获取视频的元数据(长度)?【英文标题】:How to get video's metadata (length) before uploading? 【发布时间】:2020-01-23 19:09:27 【问题描述】:

首先,我试图从文件中提取视频时长,然后显示它,而无需实际上传文件。

当用户选择视频时 - 信息将显示在视频下方,包括文件名、文件大小、文件类型。无论我的技能多么糟糕 - 我无法获得显示的持续时间。我尝试了一些从其他站点以及这里找到的代码 sn-ps,但它们似乎都不起作用。只是试图找到一个可以完成任务的简单代码。

我尝试了 onloadedmetadata,但我认为这根本行不通。

请注意:我还在学习 javascript

我还尝试了一些网站教程和一些通过 *** 找到的代码 sn-p


           function uploadFunction()
                //Variables
                var cVideo = document.getElementById("fileUp");
                var txtInfo = "";

               //function 
                if ('files' in cVideo)
                    if(cVideo.files.length == 0)
                    txtInfo = "Please select a video";
                 else 
                    for (var v = 0; v < cVideo.files.length; v++)
                        txtInfo += "<br><strong>#" + (v+1) + " File Information:</strong> <br>";         
                        var infoFile = cVideo.files[v];
                        if('name' in infoFile)
                            txtInfo += "File name: " +infoFile.name +"<br>";
                        
                        if('size' in infoFile)
                           txtInfo += "File size: " +infoFile.size +" Bytes <br>"; 
                        
                        if('type' in infoFile)
                            txtInfo += "File Type: "+infoFile.type +" <br>";
                        
                        if('duration' in infoFile)
                            txtInfo += "Duration : "+infoFile.duration +"<br>";
                        

                    
                

                
                document.getElementById("information").innerhtml = txtInfo ;
 

HTML


           <input type="file" id="fileUp" name="fileUpload" multiple size="50" onchange="uploadFunction()">
           <p id="information"></p>

根本无法获得持续时间。

【问题讨论】:

这有点令人费解,但您必须阅读。使用 javascript 文件,将其转换为 blob,将其用作视频元素的源,然后等待视频上的 metadataloaded 事件以获取视频文件的持续时间。我需要再次查看它是如何工作的...... Problem retrieving HTML5 video duration的可能重复 正如@somethinghere 所指出的,您无法通过简单地使用文件选择器元素来获取视频持续时间,您还需要创建一个视频元素并等待它加载,然后您就有了持续时间。跨度> 此外,您输入中的 File 实际上并不知道它是一个视频 - 因此所有视频特定的元数据都不存在。它只是告诉你大小是多少,所以你可以在做任何其他事情之前做一些相当基本的检查(比如阅读它)。 【参考方案1】:

这实际上相当简单,但是由于这需要将文件转换为 blob,然后使用视频元素检查其持续时间,因此上传超过几分钟的视频将需要大量处理并减慢您的页面 非常好。我添加了文件大小限制(我认为这是一个合理的开始)。这是一个 sn-p(由于沙盒限制,它不会在 Stack Overflow 上工作,但我确实在本地服务器上对其进行了测试)。我显然也不会检查 MIME 类型或它是否是视频,尽管如果您上传任何不是视频的内容,loadedmetadata 将不会触发。

const fileInput = document.querySelector( 'input[type=file]' );
const fileDuration = document.getElementById( 'file-duration' )

// Listen for any change to the value of the file input

fileInput.addEventListener( 'change', event => 

    fileDuration.textContent = 'Fetching video duration...';

    // When the file selected by the user changes:
    // - create a fresh <video> element that has not yet fired any events
    // - create a file reader to safely retrieve and manipulate the file

    const file = event.target.files[0];
    const video = document.createElement( 'video' );
    const reader = new FileReader();

    // Cancel if the initial filesize just seems too large.
    // If the maximum allowed is 30 seconds, then a Gigabyte of file seems too much.

    if( file.size > 10000000 )

        fileDuration.textContent = `File is too large ($file.size). Refused to read duration.`;
        return;

    

    // Before setting any source to the <video> element,
    // add a listener for `loadedmetadata` - the event that fires
    // when metadata such as duration is available.
    // As well as an error event is case something goes wrong.

    video.addEventListener( 'loadedmetadata', event => 

        // When the metadata is loaded, duration can be read.

        fileDuration.textContent = `Video is $video.duration seconds long.`;

    );

    video.addEventListener( 'error', event => 

        // If the file isn't a video or something went wrong, print out an error message.

        fileDuration.textContent = `Could not get duration of video, an error has occurred.`;

    );

    // Before reading any file, attach an event listener for
    // when the file is fully read by the reader.
    // After that we can use this read result as a source for the <video>

    reader.addEventListener( 'loadend', function()

        // reader.result now contains a `blob:` url. This seems like a
        // nonsensical collection of characters, but the <video> element
        // should be able to play it.

        video.src = reader.result;

        // After we assigned it to the `src` of the <video>, it will be
        // act like any other video source, and will trigger the related
        // events such as `loadedmetadata`, `canplay`, etc...

    );

    // Instruct the reader to read the file as a url. When its done
    // it will trigger the `loadend` event handler above.

    reader.readAsDataURL( file );

);
<input type="file" />
<p id="file-duration">No video file</p>

【讨论】:

谢谢!我刚刚对其进行了测试,它可以工作,但我想更好地了解代码的作用。如果你能一步一步地解释,有可能吗?如果你不介意的话。 哦,还有一件事.. 我将如何转换 console.log 以在

上显示结果?再次感谢!
@Zyaan 我已经更新了我的代码以包含 cmets 并将任何数据输出到 p 标签而不是记录它,但最后一步只不过是显示信息,所以我也做到了说它在做任何其他事情之前正在加载(这意味着人们至少会得到一些反馈)。希望它有所帮助,但代码本身非常简单且不言自明。老实说,我预计这会比实际情况更复杂。此外,对于p,您可能需要考虑不使用id,这样您可以根据需要多次重复使用此小部件。 @Zyaan 当您调用querySelector 或任何本机选择函数时,它要么返回元素,要么返回null - 只有元素有一个名为addEventListener 的方法(因为null 是,好吧,真的什么都没有,而且绝对不是可以听事件的东西)。这意味着找不到您的input。确保您的选择器实际上与您要添加侦听器的元素匹配。 您的脚本将在您将其添加到页面后立即执行,因此如果您的元素稍后在 HTML 中创建,则它根本不存在。您可以将整个脚本包装在一个函数中,并在 document 上侦听 DOMContentLoadedpageshow 事件,以便仅在解析整个 HTML 后执行它。这应该可以解决问题并保证您的脚本仅在页面上的每个元素都被实例化时才被执行。

以上是关于上传前如何获取视频的元数据(长度)?的主要内容,如果未能解决你的问题,请参考以下文章

上传前获取视频尺寸,客户端

如何获取巨大视频文件的切片数据

客户端Javascript在上传前获取视频宽度/高度

如何检索 PHAsset 的元数据?

如何在 Android 中获取视频的位置数据?

php如何获取优酷云自己上传的视频的列表?