Javascript nodejs在播放过程中获得视频

Javascript nodejs在播放过程中获得视频,javascript,html,node.js,Javascript,Html,Node.js,我已经尝试了很多年了,但没有任何进展。 我在谷歌上找到了这个 它正在运行,但当我把它放在一个函数中,并尝试在代码中使用它时,它不会运行 代码: 输出: [ Group { _name: 'vid', _video: 'vid.mp4', _master: null, _maxTime: undefined, _currentTime: 0 }, Group { _name: 'vid2', _video: 'vid2.mp4',

我已经尝试了很多年了,但没有任何进展。 我在谷歌上找到了这个 它正在运行,但当我把它放在一个函数中,并尝试在代码中使用它时,它不会运行

代码:

输出:

[
  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: 153600
duration: 4636416
movie length: 30 seconds
time scale: 153600
duration: 4636416
movie length: 30 seconds

它正确地记录了信息,但返回的是未定义的

这似乎是一个没有什么好处的大量额外工作,因此我将参考
get video duration
,它在以秒、分和小时获取任何视频文件的持续时间方面做得非常好

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

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上运行。复制您发送的要点,我得出以下结论:

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();
const fs=require(“fs”)。承诺;
班级{
构造函数(名称、视频、主控、maxTime、currentTime){
这个。_name=name;
这个._video=video;
这个。_master=master;
这是.\u maxTime=maxTime;
这是。_currentTime=currentTime;
}
setMaster(主控){
如果(此._master!=null){
这个。_master.emit('master');
}
这个。_master=master;
这个。_master.emit('master');
}
};
常量asyncForEach=async(数组,回调)=>{
for(让index=0;index{
if(文件.endsWith(“.mp4”)){
const duration=wait getVideoDuration(`${uuu dirname}/data/${file}`);
const group=新组(file.split(“.”[0],file,null,duration,0);
组。推(组);
}
});
控制台日志(组);
}
异步函数getVideoDuration(视频){
常量buff=缓冲区分配(100);
const header=Buffer.from(“mvhd”);
const file=wait fs.open(视频,“r”);
常数{
缓冲器
}=等待文件.read(buff,0,100,0);
等待文件。关闭();
const start=buffer.indexOf(header)+17;
const timeScale=buffer.readUInt32BE(开始);
const duration=buffer.readUInt32BE(start+4);
const audioLength=数学楼层((持续时间/时间刻度)*1000)/1000;
返回长度;
}
加载组();

至于您的原始代码不起作用的原因,我猜返回到
fs.open
fs.read
的回调不会返回
getVideoDuration
。我无法从
fs
文档中轻松找到返回回调值的方法,因此我只切换到Promissions和async/await,它们基本上会同步运行代码。通过这种方式,您可以保存
fs.open
fs.read
的输出,并使用它们在
getVideoDuration
范围内返回一个值,我已经看到了,但我需要在raspberry pi上运行此操作,显然该库给了我一个错误:抛出新错误(“不支持的平台/架构:”+平台);^错误:不支持的平台/体系结构:linux-arm64Aah bummer,大多数节点模块依赖于amd体系结构它运行在我的ubuntu PC上大多数PC和笔记本电脑都有amd体系结构,而大多数便携式设备(如手机和控制器)都运行arm处理器,这就是为什么它在你的ubuntu pclib上运行这个使用ffprobe的可执行文件,也许你必须安装它,我猜在回调中返回并不是在getVideoDuration中返回。您可以尝试在fs.open和fs.read前面放一个return,或者只使用这些函数的同步版本,这样您就不必处理回调,只需在末尾返回。我尝试在末尾返回,但它仍然未定义。您可以发布完整的代码吗?什么是团体目标?谢谢!我忘了在fs常量上加上承诺!返回的时间单位是多少?我需要它是第二个,因为它已经在几秒钟内。但是我有一个视频,大约40分钟长,50.223秒?说实话,我不确定这背后的数学原理,我只是根据要点改编了代码。我试着查看get video duration软件包,但它在幕后使用ffprobe,而不是从缓冲区读取数据。没关系,我找到了一种“更好”的获取持续时间的方法,我会尽快发布答案
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();