为了账号安全,请及时绑定邮箱和手机立即绑定

nodejs获取视频时长

nodejs获取视频时长

慕仙森 2022-12-22 11:43:07
我已经尝试了很长时间,但我没有取得任何进展。我在谷歌https://gist.github.com/Elements-/cf063254730cd754599e上发现了这个 ,它正在运行,但是当我把它放在一个函数中并尝试将它与我的代码一起使用时,它没有运行。代码:fs.readdir(`${__dirname}/data`, (err, files) => {        if (err) return console.error(`[ERROR] ${err}`);        files.forEach(file => {            if (file.endsWith(".mp4")) {                                // getVideoDuration(`${__dirname}/data/${file}`)                group = new Group(file.split(".")[0], file, null, getVideoDuration(`${__dirname}/data/${file}`), 0);                groups.push(group);            }        });        console.log(groups);    });function getVideoDuration(video) {    var buff = new Buffer.alloc(100);    fs.open(video, 'r', function (err, fd) {        fs.read(fd, buff, 0, 100, 0, function (err, bytesRead, buffer) {            var start = buffer.indexOf(new Buffer.from('mvhd')) + 17;            var timeScale = buffer.readUInt32BE(start, 4);            var duration = buffer.readUInt32BE(start + 4, 4);            var movieLength = Math.floor(duration / timeScale);            console.log('time scale: ' + timeScale);            console.log('duration: ' + duration);            console.log('movie length: ' + movieLength + ' seconds');            return movieLength;        });    });}输出:[  Group {    _name: 'vid',    _video: 'vid.mp4',    _master: null,    _maxTime: undefined,    _currentTime: 0  },  Group {    _name: 'vid2',    _video: 'vid2.mp4',    _master: null,    _maxTime: undefined,    _currentTime: 0  }]time scale: 153600duration: 4636416movie length: 30 secondstime scale: 153600duration: 4636416movie length: 30 seconds它正确记录信息但返回未定义
查看完整描述

3 回答

?
慕姐8265434

TA贡献1813条经验 获得超2个赞

这似乎有很多额外的工作却没有什么好处,所以我将参考get-video-duration https://www.npmjs.com/package/get-video-duration,它在获取任何视频文件的持续时间方面做得很好秒分时



查看完整回答
反对 回复 2022-12-22
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

复制你发送的要点的最后评论,我想出了这个:


const fs = require("fs").promises;


class Group {

  constructor(name, video, master, maxTime, currentTime) {

    this._name = name;

    this._video = video;

    this._master = master;

    this._maxTime = maxTime;

    this._currentTime = currentTime;

  }


  setMaster(master) {

    if (this._master != null) {

      this._master.emit('master');

    }


    this._master = master;

    this._master.emit('master');

  }

};


const asyncForEach = async (array, callback) => {

  for (let index = 0; index < array.length; index++) {

    await callback(array[index], index, array);

  }

};


async function loadGroups() {

  const files = await fs.readdir(`${__dirname}/data`);


  const groups = []


  await asyncForEach(files, async file => {


    if (file.endsWith(".mp4")) {

      const duration = await getVideoDuration(`${__dirname}/data/${file}`);

      const group = new Group(file.split(".")[0], file, null, duration, 0);

      groups.push(group);

    }

  });


  console.log(groups);

}


async function getVideoDuration(video) {

  const buff = Buffer.alloc(100);

  const header = Buffer.from("mvhd");

  const file = await fs.open(video, "r");

  const {

    buffer

  } = await file.read(buff, 0, 100, 0);


  await file.close();


  const start = buffer.indexOf(header) + 17;

  const timeScale = buffer.readUInt32BE(start);

  const duration = buffer.readUInt32BE(start + 4);


  const audioLength = Math.floor((duration / timeScale) * 1000) / 1000;


  return audioLength;

}


loadGroups();

至于为什么您的原始代码不起作用,我的猜测是在回调内部返回fs.open或fs.read不返回 for getVideoDuration。我无法轻易地从fs文档中找到一种方法来弄清楚如何返回回调的值,所以我只是切换到 promises 和 async/await,它们基本上会同步运行代码。这样您就可以保存 和 的输出,fs.open并fs.read使用它们返回 . 范围内的值getVideoDuration。


查看完整回答
反对 回复 2022-12-22
?
富国沪深

TA贡献1790条经验 获得超9个赞

我已经找到解决此问题的方法。


async function test() {

    const duration = await getDuration(`${__dirname}/data/vid.mp4`);

    console.log(duration);

}

test();


function getDuration(file) {

    return new Promise((resolve, reject) => {

        exec(`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 ${file}`, (err, stdout, stderr) => {

            if (err) return console.error(err);

            resolve(stdout ? stdout : stderr);

        });

    });

}

我只在 linux 上测试过,所以我不知道它是否可以在 windows 上运行


查看完整回答
反对 回复 2022-12-22
  • 3 回答
  • 0 关注
  • 289 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信