【问题标题】:first m3u8 ts segment not working after mp4 to m3u8 conversion by node js节点 js 将 mp4 转换为 m3u8 后,第一个 m3u8 ts 段不起作用
【发布时间】:2021-01-13 20:19:54
【问题描述】:

index.js

const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
const ffmpeg = require('fluent-ffmpeg');
const process = require('process');


const args = process.argv.slice(2);
if (args.length !== 4) {
    console.error('Incorrect number of arguments');
    process.exit(1);
  }
const startTime = args[0];
const timeDuration = args[1];
const inputFile = args[2];
const outputFile=args[3];

ffmpeg.setFfmpegPath(ffmpegPath);

ffmpeg(inputFile)
  .setStartTime(startTime)
  .setDuration(timeDuration)
  .output(outputFile)
  .outputOptions('-hls_list_size 0')
  .on('end', function(err) {
    if(!err) { console.log('conversion Done') }
  })
  .on('error', function(err){
    console.log('error: ', err)
  }).run();

这是 index.js,我通过在终端上点击命令来运行它

node index.js 5 40 ./input.mp4 ./output.m3u8

这里 5 是开始时间,40 是持续时间,以秒为单位。该过程使用 ts 文件创建 m3u8,但未正确创建第一个 ts 文件。它以 kb 格式创建,而所有其他文件以 mb 格式创建。

output_test0 没有正确生成,这就是为什么在播放 m3u8 文件时,前几秒只是静态图片。此问题仅发生在第一个 ts 输出中。有什么技巧可以解决吗?

【问题讨论】:

  • 您确定不是视频播放器的问题吗?尝试直接在终端执行ffmpeg命令排除node.js,看看结果是否不同。
  • 我在命令行中试过这个``` ffmpeg -i f1.mp4 -profile:v baseline -level 3.0 -s 640x360 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls index.m3u8` ``它工作得很好。我也尝试在节点 js 中设置输出选项,但第一个 ts 文件仍然无法正常工作
  • 使用the start event 打印命令行并配置您的node.js 代码以获得与您已知的命令行等效的命令行。
  • 我发现了问题。这是正确的命令行“ffmpeg -i test.m3u8 -ss 6.2 -y -t 45 -profile:v baseline -level 3 -start_number 0 -hls_list_size 0 -f hls output_test.m3u8”。但是节点js在命令行中传递这个“ffmpeg -ss 6.2 -i test.m3u8 -y -t 45 -profile:v baseline -level 3 -start_number 0 -hls_list_size 0 -f hls output_test.m3u8”基本上是-ss [start_time ] 应该在 -i [input] 之后。任何技巧如何解决这个问题?该命令需要输出搜索。这里是文档链接trac.ffmpeg.org/wiki/Seeking

标签: node.js express ffmpeg fluent-ffmpeg


【解决方案1】:

在您评论它似乎是由使用输入搜索而不是输出搜索引起的:

使用seek()seekOutput() 而不是setStartTime()The documentation 描述了区别:

seek(time): 寻找输出


别名: seekOutput()

在将流编码到输出之前寻找流。这与调用 seekInput() 不同之处在于偏移量仅适用于一个输出。这也比较慢,因为跳过的帧仍然会被解码(但会被丢弃)。

时间参数可以是数字(以秒为单位)或时间戳字符串(格式为 [[hh:]mm:]ss[.xxx])。

ffmpeg('/path/to/file.avi')
  .seekInput('1:00')

  .output('from-1m30s.avi')
  .seek(30)

  .output('from-1m40s.avi')
  .seek('0:40');

setStartTime()seekInput() 的别名。来自the same documentation

seekInput(time):设置输入开始时间


别名: setStartTime()

寻找输入并仅在给定时间偏移处开始解码。

请注意,seek()seekOutput() 应应用于输出,而不是作为seekInput() 应用于输入,即在output() 之后。

【讨论】:

  • 谢谢,我已经解决了。这是我更新代码的链接codesandbox.io/s/modest-brahmagupta-8dins 基本上我所做的是删除 setStartTime() 并将其替换为 outputOption('-ss',startTime) ,为此命令变为 -i [file path] -ss [start_time ]。现在它是输出搜索格式,所以它工作了。谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 2018-11-18
  • 1970-01-01
相关资源
最近更新 更多