concat视频的时候会出现这个问题导致视频出现播放卡顿,无声音等问题
ffmpeg -f concat -i input.txt -c copy output.mp4
使用上面的命令由于视频的时间戳问题会导致类似的问题,改成下面的方式问题基本解决,但是相对麻烦了许多
ffmpeg -i input1.mp4 -i input2.webm -i input3.mov -filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]concat=n=3:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mkv
[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]
[0:v:0] input1.mp4的视频流 stream 0
[0:a:0] input1.mp4的音频流 stream 0,音频可能会有多个轨道
concat=n=3:v=1:a=1[outv][outa]
n=3 表示有3个视频,v=1 表示每个片段将有一个视频流,a=1 表示每个片段将有一个音频流,
[outv][outa] 表示输出流的名称
下面是go语言的实现方法
package main
import (
"fmt"
"io"
"os"
"os/exec"
"sort"
"strconv"
"strings"
)
var ds string = string(os.PathSeparator)
func main() {
// 修改成自己的文件夹
dir := "/input"
files, err := os.ReadDir(dir)
if err != nil {
fmt.Println("读取目录时发生错误:", err)
return
}
// 根据文件名排序,文件名为数字
sort.Slice(files, func(i, j int) bool {
prev, _ := strconv.Atoi(fileNameWithoutExt(files[i].Name()))
next, _ := strconv.Atoi(fileNameWithoutExt(files[j].Name()))
return prev < next
})
var args []string
var filterComplex []string
index := 0
for _, file := range files {
if file.IsDir() {
continue
}
fileName := file.Name()
if !isVideoByExt(fileName) {
continue
}
input := dir + ds + fileName
args = append(args, "-i", input)
filterComplex = append(filterComplex, fmt.Sprintf("[%d:v:0][%d:a:0]", index, index))
index++
}
if index == 0 {
fmt.Println("目录为空!")
return
}
filterComplex = append(filterComplex, fmt.Sprintf("concat=n=%d:v=1:a=1[outv][outa]", index))
args = append(args, "-filter_complex", strings.Join(filterComplex, ""), "-map", "[outv]", "-map", "[outa]")
// "-c:v", "libx264" 设置编码为h.264,也可以修改成其它编码,不同编码配置不同,libx265编码是一样的
// "-crf", "18" 码率和编码速度,值越高视频越模糊,18基本为无损
args = append(args, "-c:v", "libx264", "-crf", "18", "output.mp4")
cmd("ffmpeg.exe", args)
}
func isVideoByExt(filename string) bool {
extension := getFileExt(filename)
// 常见的视频文件扩展名
videoExtensions := []string{"mp4", "avi", "mov", "wmv", "mkv"}
for _, ext := range videoExtensions {
if extension == ext {
return true
}
}
return false
}
func getFileExt(filename string) string {
return strings.ToLower(filename[strings.LastIndex(filename, ".")+1:])
}
func fileNameWithoutExt(filePath string) string {
fileName := filepath.Base(filePath)
fileName = strings.TrimSuffix(fileName, filepath.Ext(filePath))
return fileName
}
func cmd(name string, args []string) {
cmd := exec.Command(name, args...)
// 获取命令的标准输出和标准错误管道
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("无法创建标准输出管道:", err)
return
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("无法创建标准错误管道:", err)
return
}
// 启动命令的异步执行
if err := cmd.Start(); err != nil {
fmt.Println("启动命令时发生错误:", err)
return
}
// 实时打印标准输出到控制台
go func() {
io.Copy(os.Stdout, stdout)
}()
// 实时打印标准错误到控制台
go func() {
io.Copy(os.Stderr, stderr)
}()
// 等待命令执行完成
if err := cmd.Wait(); err != nil {
fmt.Println("命令执行时发生错误:", err)
return
}
}
参考资料