Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/91.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 输入视频文件时获取视频持续时间_Javascript_Html - Fatal编程技术网

Javascript 输入视频文件时获取视频持续时间

Javascript 输入视频文件时获取视频持续时间,javascript,html,Javascript,Html,我正在用HTML和Javascript做一个项目,它将在本地文件中运行。 我需要通过输入选择一个文件,获取其信息,然后决定是否将其添加到列表中并复制。如果我决定使用它,我必须把它放在队列中,以便以后使用。否则,我将放弃并选择另一个文件 我所面临的问题是,我找不到一种方法来获得视频的持续时间,仅仅通过选择它的输入 我搜索了很多,但没有找到任何方法来获取持续时间。在下面的代码中,我尝试使用“file.duration”,但它不起作用,它只返回“undefined” 这是我的输入,正如你所看到的正常

我正在用HTML和Javascript做一个项目,它将在本地文件中运行。 我需要通过输入选择一个文件,获取其信息,然后决定是否将其添加到列表中并复制。如果我决定使用它,我必须把它放在队列中,以便以后使用。否则,我将放弃并选择另一个文件

我所面临的问题是,我找不到一种方法来获得视频的持续时间,仅仅通过选择它的输入

我搜索了很多,但没有找到任何方法来获取持续时间。在下面的代码中,我尝试使用“file.duration”,但它不起作用,它只返回“undefined”

这是我的输入,正如你所看到的正常

<div id="input-upload-file" class="box-shadow">
   <span>upload! (ღ˘⌣˘ღ)</span> <!--ignore the text face lol -->
   <input type="file" class="upload" id="fileUp" name="fileUpload" onchange="setFileInfo()">
</div>
有办法做到这一点吗?如果没有,有哪些替代方法可以帮助我?

在中,您可以使用URL API和非附加视频元素来加载文件的内容

var myVideos=[];
window.URL=window.URL | | window.webkitURL;
document.getElementById('fileUp')。onchange=setFileInfo;
函数setFileInfo(){
var files=this.files;
myVideos.push(文件[0]);
var video=document.createElement('video');
video.preload='元数据';
video.onloadedmetadata=函数(){
window.URL.revokeObjectURL(video.src);
var duration=video.duration;
myVideos[myVideos.length-1]。持续时间=持续时间;
更新信息();
}
video.src=URL.createObjectURL(文件[0]);;
}
函数updateInfo(){
var infos=document.getElementById('infos');
infos.textContent=“”;
对于(var i=0;i

上传!(ღ˘⌣˘ღ)

在继续执行更多代码之前,我需要验证一个文件,下面是我的方法,借助Kaido的回答

用户上载文件时的onchange事件:

$("input[type=file]").on("change", function(e) {

    var file = this.files[0]; // Get uploaded file

    validateFile(file) // Validate Duration

    e.target.value = ''; // Clear value to allow new uploads
})
现在验证持续时间:

function validateFile(file) {

    var video = document.createElement('video');
    video.preload = 'metadata';

    video.onloadedmetadata = function() {

        window.URL.revokeObjectURL(video.src);

        if (video.duration < 1) {

            console.log("Invalid Video! video is less than 1 second");
            return;
        }

        methodToCallIfValid();
    }

    video.src = URL.createObjectURL(file);
}
函数验证文件(文件){
var video=document.createElement('video');
video.preload='元数据';
video.onloadedmetadata=函数(){
window.URL.revokeObjectURL(video.src);
如果(视频持续时间<1){
console.log(“无效视频!视频小于1秒”);
返回;
}
方法Callifvalid();
}
video.src=URL.createObjectURL(文件);
}

这里是异步/等待承诺版本:

const loadVideo = file => new Promise((resolve, reject) => {
    try {
        let video = document.createElement('video')
        video.preload = 'metadata'

        video.onloadedmetadata = function () {
            resolve(this)
        }

        video.onerror = function () {
            reject("Invalid video. Please select a video file.")
        }

        video.src = window.URL.createObjectURL(file)
    } catch (e) {
        reject(e)
    }
})
可按如下方式使用:

const video = await loadVideo(e.currentTarget.files[0])
console.log(video.duration)

这就是我在将其推到S3之前获取视频持续时间的方法。。 我使用这段代码上传4+GB的视频文件,并与Reactjs配合使用

注意-对于.avi、.flv、.vob、.mpeg等格式,将找不到持续时间,因此请通过向用户发送简单消息来处理它


FileReader
获取视频持续时间很简单,在
async/await
中也很容易管理

用于反应

const getVideoDuration = file =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      const media = new Audio(reader.result);
      media.onloadedmetadata = () => resolve(media.duration);
    };
    reader.readAsDataURL(file);
    reader.onerror = error => reject(error);
  });
其中
文件
文件
对象


Codesandbox:

你在找这样的东西吗?这不是我的,它是用于音频的,但我无法想象它对我来说会有什么不同video@RobinHellemans这一个创建了一个元素,这正是我不想要的(你知道如何使用avi文件来完成这项工作吗?这项工作做得很好,但在我返回值之前,这项工作还可以,但在我返回值之后,它是未定义的。你知道我能做些什么来解决这个问题吗?例如,24.105 UnfinedEYEP,将其存储在全局变量中,或者更好,将文件存储在数组中,然后在事件处理程序中,将dur添加到存储的文件中。)电离attribute@davis,请参见编辑,然后可以使用
myVideos.splice(视频的索引)删除不需要的文件
噢,这对我帮助很大,谢谢!还有,为什么我不能将此信息发送到函数外部?即使使用getter和setter,我仍然无法执行此操作。这是因为您在视频的
onmetadata
中,它是异步工作的。您必须将其存储在全局变量中(就像我使用
myVideos=[];
)并且仅在触发此事件后调用您的
setFileInfo()
。或者,您也可以使用
setTimeout()
循环检查属性是否已设置。typescript抱怨如果将
loadVideo
的返回类型指定为
PromiseLike
,则将
传递给
resolve
。抛出错误
类型为“GlobalEventHandlers”的参数不能分配给类型为“HTMLVideoElement | PromiseLike”的参数。
要解决此问题,只需将
video
对象本身传递给
resolve
,而不是
this
,例如
resolve(video)
为什么要向下投票?您能解释一下这里的错误吗?
  //same method can be used for images/audio too, making some little changes
  getVideoDuration = async (f) => {
    const fileCallbackToPromise = (fileObj) => {
      return Promise.race([
        new Promise((resolve) => {
          if (fileObj instanceof HTMLImageElement) fileObj.onload = resolve;
          else fileObj.onloadedmetadata = resolve;
        }),
        new Promise((_, reject) => {
          setTimeout(reject, 1000);
        }),
      ]);
    };

    const objectUrl = URL.createObjectURL(f);
    // const isVideo = type.startsWith('video/');
    const video = document.createElement("video");
    video.src = objectUrl;
    await fileCallbackToPromise(video);
    return {
      duration: video.duration,
      width: video.videoWidth,
      height: video.videoHeight,
    };
}


//call the function
//removing unwanted code for clarity
const meta = await this.getVideoDuration(file);
//meta.width, meta.height, meta.duration is ready for you to use
const getVideoDuration = file =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      const media = new Audio(reader.result);
      media.onloadedmetadata = () => resolve(media.duration);
    };
    reader.readAsDataURL(file);
    reader.onerror = error => reject(error);
  });
const duration = await getVideoDuraion(file);