在 Linux 中使用 FFMPEG 覆盖 TS 流文件



我正在尝试将 rtmp 流转换为 m3u8 流。为了达到这个目标,我使用FFMPEG。现在,转换和下载没有问题。但是,它会写入大量.ts文件,例如channel0000.ts,channel0001.ts,channel0002.ts。每 10 秒创建 1 个 ts 文件。在这一点上,我想要一个 ts 文件。换句话说,我需要覆盖,因为我不想存储我需要的最后 10 秒的所有流。当我尝试在同一文件上写入时,出现此错误:

Invalid segment filename template 'channel.ts'
Could not write header for output file #0 (incorrect codec parameters ?):   Invalid argumentStream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:1 -> #0:1 (copy)
Last message repeated 1 times

这是我的 FFMPEG 命令。

ffmpeg -loglevel quiet -i rtmp://example -c:v libx264 -profile:v baseline -level 3.1 -c:a aac -strict experimental -f mpegts - | ffmpeg -i - -c copy -map 0 -f segment -segment_list channel.m3u8 -segment_format mpegts -segment_time 10 channel%04d.ts

有什么建议吗?

在FFMPEG文档中,我找到了">segment_wrap"选项。添加此选项时,文件将循环写入。就我而言,我添加了">-segment_wrap 1"命令部分,它现在只写入一个文件。

我有一个类似的问题,我的解决方案是管道输出hls复用器的整个结果,除了使用-hls_segment_filename pipe:1选项的头文件(因此我只是管道 .ts 文件而不是 .m3u8 文件(。

在我的管道上,我卡了一段我写的代码来检测 .ts 文件的标头,它看起来像字节 [71, 64,17, 1X, 0, 66, 240, 34, 0, 1, 193, 0, 0, 255, 1, 255, 0, 1, 252, 128, 17, 72](如果您希望更多标头进行区分,我建议 GHex 检查您的 .ts 文件(。然后,我编写了一段代码,沿着这一行剪切(警告,这里的第四个字节可以更改其值,但它是唯一的一个(,并重构文件。

我认为对于您的应用程序,剩下唯一要做的就是对文件的内容使用队列。如果你想要十秒,而你的文件大约是1秒,你可以使用长度为10的队列。

我的代码是 go 的(因为我的整个项目都是(,所以这里有一些 go 代码可能会有所帮助:

type tsFile struct {
contents []byte
finished bool
child *tsFile
}
func in(a int, array int[]) bool{
for _, b := range list {
if b == a {
return true
}
}
return false
}
func CutAdd(curFile *tsFile, pipedOut []bytes){
header := [...]bytes{} // insert here the header you want
unNeededIndex := [...]int{3} // insert here the bytes indexes that change between files
cur_header_pointer := 0
header_cache := make([]byte, 0, len(header))
for i, b := range(pipedOut){
if header[cur_header_pointer] == b || in(cur_header_pointer, unNeededIndex){
header_cache = append(header_cache, b)
cur_header_pointer ++
if cur_header_pointer == len(header){
curFile.finished = true
curFile.child = &tsFile{contents : header_cache}
CutAdd(curFile.child, pipedOut[i:])
return
}
} else {
if cur_header_pointer != 0 {
for _, cached_b := range(header_cache){
curFile.contents = append(curFile.contents, cached_b) // we store what we thought was a header
}
cur_header_pointer = 0
}
curFile.contents = append(curFile.contents, b) // we store the byte
}
}
}

它有点卡顿,但它对我有用(也可能有错误,我没有放我当时制作的实际代码,但你应该大致了解我的意思(

最新更新