V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
littleNorth
V2EX  ›  程序员

请教 ffmpeg 合成视频

  •  
  •   littleNorth · 2023-03-20 19:49:38 +08:00 via Android · 2018 次点击
    这是一个创建于 616 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我在安卓上用 ffmpeg 开发,之前对视频和 ffmepg 完全没有了解是个突然来的需求。
    比如将两个 mp4 格式视频(两个分辨率都是 1920×1080 ,手机上拍的,其中一个播放器上识别为竖屏播放,一个播放器上识别为横屏播放)按照网上教程转换成两个相同分辨率( 1280×720 )的 ts 格式再去按时间前后合并,合并后第一个竖屏视频,两边有黑边中间是一个竖的视频没问题,但是第二个横屏的视频也被挤压在竖屏视频显示的空间内了,请教下如何让第二个横屏视频能够满屏显示?
    19 条回复    2023-03-24 08:49:47 +08:00
    em70
        1
    em70  
       2023-03-20 19:53:55 +08:00
    问过 chatgpt 了吗
    mxT52CRuqR6o5
        2
    mxT52CRuqR6o5  
       2023-03-20 19:55:30 +08:00
    我感觉需要确认一下「两个分辨率都是 1920×1080 」这件事,我咋感觉其中一个视频是 1080x1920
    littleNorth
        3
    littleNorth  
    OP
       2023-03-20 20:23:44 +08:00 via Android
    @em70 问了一个礼拜了,他倒是给了些答案,但这个我描述给它,它似乎有点呆
    littleNorth
        4
    littleNorth  
    OP
       2023-03-20 20:26:25 +08:00 via Android
    @mxT52CRuqR6o5 就是我看视频的详细信息里面,都是 1920×1080 ,而且我在转换成 ts 格式时候是统一转成 1280×720 的分辨率,单独点开两个 ts 格式的视频,也是正常的,就是合拢时候会有问题,后面一个视频会只在第一个视频的显示区域显示,被拉伸的很厉害
    muzuiget
        5
    muzuiget  
       2023-03-21 01:13:15 +08:00
    可能 1920×1080 竖屏的视频,已经加了黑边了,同分辨率同编码,直接不转码合并就行了。
    loginv2
        6
    loginv2  
       2023-03-21 09:19:50 +08:00
    竖屏有两种,一种是像素就是这么排列的,一种是文件头会告诉你这个播放角度。要先确认这个问题。
    jifengg
        7
    jifengg  
       2023-03-21 09:29:55 +08:00
    1.转 720p 的时候你两个视频的转码参数是一样的吗?(按理你不能用同样的参数,因为竖屏的要有左右黑边)
    2.确认一下第二个视频转出来的 ts 是否正常。
    jifengg
        8
    jifengg  
       2023-03-21 09:32:12 +08:00
    另外,你可以把你的转码、合并的 ffmpeg 参数列出来,比较好看出问题。
    以及,你期望两个视频合成一个后是什么效果,是第一个左右黑边,第二个正常填充满,对吗
    littleNorth
        9
    littleNorth  
    OP
       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
        10
    littleNorth  
    OP
       2023-03-21 09:42:46 +08:00
    @muzuiget 我用 ffprobe 看这个竖屏的视频,他有一个参数是这个样的:
    Side data:
    displaymatrix: rotation of -90.00 degrees
    不清楚这个是否就是你说的播放角度?
    littleNorth
        11
    littleNorth  
    OP
       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
        12
    littleNorth  
    OP
       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
        13
    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
        14
    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
        15
    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
        16
    littleNorth  
    OP
       2023-03-22 09:46:34 +08:00
    @jifengg 太感谢了 昨天换了你这个指令基本把合成这块能搞定了。就是合成后有时候其中一个视频会卡顿和比较快的播放,这个原因是不是从指令方面没法解决?我搜了下说是可能手机上的硬件没有 PC 好所以会有掉帧等情况
    jifengg
        17
    jifengg  
       2023-03-22 12:25:33 +08:00
    @littleNorth 你还是得先确定问题所在。
    比如你把最终视频放 pc 上播放,看看是否正常。
    目前手机的硬解码,按理来说针对 720p h264 的视频,是完全足够的。
    littleNorth
        18
    littleNorth  
    OP
       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
        19
    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 会比较难写,以及会比较长且难以维护
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1174 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:02 · PVG 07:02 · LAX 15:02 · JFK 18:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.