请教 ffmpeg 合成视频

2023-03-20 19:49:38 +08:00
 littleNorth
我在安卓上用 ffmpeg 开发,之前对视频和 ffmepg 完全没有了解是个突然来的需求。
比如将两个 mp4 格式视频(两个分辨率都是 1920×1080 ,手机上拍的,其中一个播放器上识别为竖屏播放,一个播放器上识别为横屏播放)按照网上教程转换成两个相同分辨率( 1280×720 )的 ts 格式再去按时间前后合并,合并后第一个竖屏视频,两边有黑边中间是一个竖的视频没问题,但是第二个横屏的视频也被挤压在竖屏视频显示的空间内了,请教下如何让第二个横屏视频能够满屏显示?
2046 次点击
所在节点    程序员
19 条回复
em70
2023-03-20 19:53:55 +08:00
问过 chatgpt 了吗
mxT52CRuqR6o5
2023-03-20 19:55:30 +08:00
我感觉需要确认一下「两个分辨率都是 1920×1080 」这件事,我咋感觉其中一个视频是 1080x1920
littleNorth
2023-03-20 20:23:44 +08:00
@em70 问了一个礼拜了,他倒是给了些答案,但这个我描述给它,它似乎有点呆
littleNorth
2023-03-20 20:26:25 +08:00
@mxT52CRuqR6o5 就是我看视频的详细信息里面,都是 1920×1080 ,而且我在转换成 ts 格式时候是统一转成 1280×720 的分辨率,单独点开两个 ts 格式的视频,也是正常的,就是合拢时候会有问题,后面一个视频会只在第一个视频的显示区域显示,被拉伸的很厉害
muzuiget
2023-03-21 01:13:15 +08:00
可能 1920×1080 竖屏的视频,已经加了黑边了,同分辨率同编码,直接不转码合并就行了。
loginv2
2023-03-21 09:19:50 +08:00
竖屏有两种,一种是像素就是这么排列的,一种是文件头会告诉你这个播放角度。要先确认这个问题。
jifengg
2023-03-21 09:29:55 +08:00
1.转 720p 的时候你两个视频的转码参数是一样的吗?(按理你不能用同样的参数,因为竖屏的要有左右黑边)
2.确认一下第二个视频转出来的 ts 是否正常。
jifengg
2023-03-21 09:32:12 +08:00
另外,你可以把你的转码、合并的 ffmpeg 参数列出来,比较好看出问题。
以及,你期望两个视频合成一个后是什么效果,是第一个左右黑边,第二个正常填充满,对吗
littleNorth
2023-03-21 09:40:52 +08:00
@jifengg 你好 下面这行参数就是我用来转两个视频的参数(两个视频都是用这个来转的),基本靠 chatgpt 给的参数拼凑出来的
转换的指令:
-ss startTime -i input.mp4 -to endTime -filter:v scale=1280:720,pad=1280:720:(ow-iw)/2:(oh-ih)/2:black -r 30 -b:v 5000k -c:a copy -c:v libx264 -vbsf h264_mp4toannexb -bsf:a aac_adtstoasc output.ts
合成的指令:
-i concat:input1.ts|input2.ts -c:v copy -c:a copy -strict -2 -bsf:a aac_adtstoasc newOutPath.mp4
对的,就是你说的前面先放那个竖屏视频,两边有黑边,放完就紧接着放后面那个填满的视频。
littleNorth
2023-03-21 09:42:46 +08:00
@muzuiget 我用 ffprobe 看这个竖屏的视频,他有一个参数是这个样的:
Side data:
displaymatrix: rotation of -90.00 degrees
不清楚这个是否就是你说的播放角度?
littleNorth
2023-03-21 09:44:19 +08:00
我贴一下原视频的参数
竖视频:
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2023-03-15T05:48:26.000000Z
com.android.version: 11
com.android.capture.fps: 30.000000
Duration: 00:00:09.27, start: 0.000000, bitrate: 18806 kb/s
Stream #0:0[0x1](eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt470bg/bt470bg/smpte170m, progressive), 1920x1080, 18265 kb/s, SAR 1:1 DAR 16:9, 29.89 fps, 30 tbr, 90k tbn (default)
Metadata:
creation_time : 2023-03-15T05:48:26.000000Z
handler_name : VideoHandle
vendor_id : [0][0][0][0]
Side data:
displaymatrix: rotation of -90.00 degrees
Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 192 kb/s (default)
Metadata:
creation_time : 2023-03-15T05:48:26.000000Z
handler_name : SoundHandle
vendor_id : [0][0][0][0]
横视频:
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2023-03-15T07:46:17.000000Z
location : +31.2324+121.4605/
location-eng : +31.2324+121.4605/
com.android.version: 10
Duration: 00:00:10.43, start: 0.000000, bitrate: 20894 kb/s
Stream #0:0[0x1](eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt470bg/bt470bg/smpte170m, progressive), 1920x1080, 20176 kb/s, SAR 1:1 DAR 16:9, 30 fps, 120 tbr, 90k tbn (default)
Metadata:
creation_time : 2023-03-15T07:46:17.000000Z
handler_name : VideoHandle
vendor_id : [0][0][0][0]
Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 96 kb/s (default)
Metadata:
creation_time : 2023-03-15T07:46:17.000000Z
handler_name : SoundHandle
vendor_id : [0][0][0][0]
littleNorth
2023-03-21 09:45:19 +08:00
这是我合成出来的视频,也就是有问题画面会被拉伸的那个:
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.40.101
Duration: 00:00:23.01, start: 0.000000, bitrate: 5124 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, progressive), 1280x720 [SAR 81:256 DAR 9:16], 5021 kb/s, 30 fps, 30 tbr, 90k tbn (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 96 kb/s (default)
Metadata:
handler_name : SoundHandler
entro
2023-03-21 10:49:30 +08:00
ffprobe -i input.mp4 -show_streams | grep rotation
把存在 rotation 的文件元数据中的 rotation 去掉再合并试试
ffmpeg -i input.mp4 -vf "transpose=1,transpose=2" -codec:a copy output.mp4
jifengg
2023-03-21 10:51:07 +08:00
需要明确一下你使用的 ffmpeg 版本。
“-filter:v scale=1280:720,pad=1280:720:(ow-iw)/2:(oh-ih)/2:black”
用你的命令 scale=1280:720 ,在 ffmpeg 4 以上的版本,竖屏视频被拉伸(没黑边),横屏视频是正常的。
把 scale 这块改成 “scale=720*iw/ih:720”,就能满足你的预期,合并出来的视频也是 ok 的。

所以,我觉得你如果第一个视频能正常转出带黑边的,可能是 ffmpeg 版本的问题。或者是你的参数根本就不是这么写
Hccake
2023-03-21 20:39:34 +08:00
竖视频实际是横向的,只不过 metadata 中有个 rotation 参数,会让播放器识别,转向后播放。
仅仅删除 metadata 可以使用:
```shell
ffmpeg -i origin.mp4 -c copy -metadata:s:v:0 ratate=0 output.mp4
```
这样就会得到一个横向的视频。

如果想将视频实际方向修改为竖向,可以使用:
```shell
ffmpeg -i orgin.mp4 -vf "transpose=1" output.mp4
```
littleNorth
2023-03-22 09:46:34 +08:00
@jifengg 太感谢了 昨天换了你这个指令基本把合成这块能搞定了。就是合成后有时候其中一个视频会卡顿和比较快的播放,这个原因是不是从指令方面没法解决?我搜了下说是可能手机上的硬件没有 PC 好所以会有掉帧等情况
jifengg
2023-03-22 12:25:33 +08:00
@littleNorth 你还是得先确定问题所在。
比如你把最终视频放 pc 上播放,看看是否正常。
目前手机的硬解码,按理来说针对 720p h264 的视频,是完全足够的。
littleNorth
2023-03-23 17:28:57 +08:00
@jifengg 你好,可以再请教一下吗?
我用了这个指令( scale=trunc(720*iw/ih/2)*2:720,pad=1280:720:(ow-iw)/2:(oh-ih)/2:black ),遇到一个 550*270 的视频,高度缩放到 720 后,宽度为 1466 ,超过了 pad 的 1280 就报错了,请教下我这边可以怎么改可以能比较好的自适应?,我尝试了删掉了后面的 pad 参数,但是发现视频会被拉伸,所以不清楚这个 pad 这边可以怎么改。
jifengg
2023-03-24 08:49:47 +08:00
@littleNorth 首先你是用安卓开发对吧,那就不是直接用 ffmpeg 命令,我之前给你改成 “scale=720*iw/ih:720” ,是让 ffmpeg 自己去计算缩放后的宽度,不需要提前算好,但是兼容性没那么好。
两个方法,
1 ,在调用 ffmpeg 之前,你自己把视频要缩放的宽高计算好,不要溢出 pad 即可;
好处是代码能比较清晰,后续修改方便,前提是你需要先获取到视频的分辨率和旋转角度信息( rotation )

2 ,修改 scale ,需要增加 if 判断,让 ffmpeg 来做方法 1 里的判断,如果 视频比较宽(跟你 pad 的宽高比做比较),就固定宽度为 1280 ,计算高度;如果视频比较窄,就固定高度,计算宽度;
好处是不需要第三方代码,写好的话能自动适应任何分辨率的视频;坏处就是,这个 if 会比较难写,以及会比较长且难以维护

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/925648

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX