解决ffmpeg的Non-monotonous DTS in output stream 0:1

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
	}
}

参考资料 

ffmpeg合并视频

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值