最新消息:20210917 已从crifan.com换到crifan.org

【已解决】ffmpeg合并字幕到视频下方指定位置

视频 crifan 1771浏览 0评论
折腾:
【未解决】把视频画面增加高度再合并字幕到指定位置
期间,已有一个srt文件和(扩大了高度的视频),现在希望去把字幕嵌入到视频下方部分,最好能指定位置。
对于指定额外属性:
srt貌似不支持,之前接触过ass好像可以:
包括字幕背景色,字体大小和颜色等等。
先去把srt嵌入式视频中再说。
后续再看能否指定嵌入字幕的位置以及其他额外属性。
之前其实已经有过类似经验:
【已解决】ffmpeg从mp4视频提取出srt和ass字幕文件
【已解决】Mac中用ffmpeg调整mp4默认字幕为中文
【已解决】ffmpeg集成srt字幕到视频的字幕流中即软字幕
ffmpeg -i CTT_Folge_01_CH_Subs_DefaultZhcnButNotShow.mp4 -i subtitle.srt -codec copy -map 0  softSubtitle.mp4
ffmpeg -i CTT_Folge_01_CH_Subs_DefaultZhcnButNotShow.mp4 -i subtitle.srt -c copy -c:s mov_text movTextSubtitle.mp4
【已解决】ffmpeg嵌入硬编码烧录ass字幕到视频中即字幕成为视频内容本身
ffmpeg -i CTT_Folge_01_CH_Subs_DefaultZhcnButNotShow.mp4 -vf ass=subtitle.ass burnedInAssSubtitle.mp4
对应指定字幕属性可以参考之前的:
【已解决】调节ass字幕配置字幕字体大小和背景色再用ffmpeg嵌入视频中
【已解决】ass字幕文件中如何设置字幕的半透明背景色
【已解决】用Aegisub字幕编辑器去调整字体大小和字幕背景半透明效果
还是去研究看看参数
搞清楚,字幕嵌入到视频中,是soft软字幕=其中一个stream 还是 硬字幕=hard=字幕变成视频数据本身
ffmpeg merge srt
mp4 – Use ffmpeg to add text subtitles – Stack Overflow
ffmpeg -i infile.mp4 -i infile.srt -c copy -c:s mov_text outfile.mp4

-vf subtitles=infile.srt will not work with -c copy
此种做法是:软字幕
  • 需要播放器支持解析字幕的流
    • 比如VLC
在ffmpeg已安装了ass支持的库libass的前提下,去:
ffmpeg -i mymovie.mp4 -vf ass=subtitles.ass mysubtitledmovie.mp4
此种做法是:硬字幕=hard=字幕被 burn 烧录 到 视频中=字幕变成视频数据的一部分
How to Add Font size in subtitles in ffmpeg video filter – Stack Overflow
解释更清楚:
硬字幕=hardsubs=hard subs=hard subtitles=burn in subtitles:
用-vf参数:
ffmpeg -i video.mp4 -vf "subtitles=subs.srt:force_style='Fontsize=24,PrimaryColour=&H0000ff&'" -c:a copy output.mp4
软字幕=soft subs=soft subtitles:
用stream copy流拷贝模式:
ffmpeg -i input.mkv -i subtitles.ass -codec copy -map 0 -map 1 output.mkv
关于参数的解释详见官网:
FFmpeg Filters Documentation
“10.187 subtitles
Draw subtitles on top of input video using the libass library.”
但是写的是:在输入视频的上方显示字幕,而不是希望的,指定位置,视频的下方显示字幕
后记:此处top不是字幕位置,而是z轴,显示的layer层次,即字幕的layer在video的layer之上
Add SRT subtitle to video with ffmpeg – Stack Overflow
video – Adding multiple subtitle streams to MP4 with FFMPEG – Stack Overflow
ffmpeg command to add .srt based subtitles to an .mkv file
Embed SRT file into mp4 with ffmpeg
ffmpeg -i infile.mp4 -f srt -i infile.srt -c:v copy -c:a copy -c:s mov_text outfile.mp4 
所以还要继续找:
如何烧录字幕到视频时,还能指定字幕位置
那还是继续研究参数
-vf “subtitles=subs.srt:…”
HowToBurnSubtitlesIntoVideo – FFmpeg
不过官网解释的逻辑相对比较清楚:
支持burn烧录字幕到视频中=硬字幕
有两种filter过滤器:
  • subtitles=srt
  • ass
【硬字幕:subtitles】
效果:用libass库实现了,在输入的视频 上方 显示字幕
前提:ffmpeg开启了libass=编译时加了参数–enable-libass
详见:http://ffmpeg.org/ffmpeg-filters.html#subtitles-1
实现方式:
方式1:有单独的字幕文件 :subtitle.srt
ffmpeg -i video.avi -vf subtitles=subtitle.srt out.avi
方式2:字幕是内嵌在container容器中,比如mkv视频本身video.mkv
ffmpeg -i video.mkv -vf subtitles=video.mkv out.avi
【硬字幕:ass】
效果和逻辑:
  • 类似于上面的subtitles的filter,不过不需要libavcodec和libavformat
前提:ffmpeg开启了libass=编译时加了参数–enable-libass
限制:仅限于ass字幕文件
详见:http://ffmpeg.org/ffmpeg-filters.html#ass
方式:
ffmpeg -i video.avi -vf "ass=subtitle.ass" out.avi
另外:
也支持:Picture-based subtitles=基于图片的字幕
方式:
ffmpeg -i input.mkv -filter_complex "[0:v][0:s]overlay[v]" -map "[v]" -map 0:a <output options> output.mkv
参数说明:
  • 如果是多个stream流,可以把[0:s] 换成对应的 [0:s:0] 或 [0:s:1]
注意:
当视频有多个音频流,此种方式可能会破坏编码,则用下面方式去修复:
ffmpeg -i input.ts -filter_complex "[0:v][0:s]overlay[v]" -map "[v]" -map 0:a:0 <output options> output.mkv
Windows环境:注意设置字体的路径
详见:
enable libass – Page 3 – FFmpeg
先确认此处的ffmpeg是开启ass的编译参数
–enable-libass
的:
# ffmpeg -version
ffmpeg version 4.2-tessus  https://evermeet.cx/ffmpeg/  Copyright (c) 2000-2019 the FFmpeg developers
built with Apple LLVM version 10.0.1 (clang-1001.0.46.4)
configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libmysofa --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvmaf --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-version3 --pkg-config-flags=--static --disable-ffplay
libavutil      56. 31.100 / 56. 31.100
libavcodec     58. 54.100 / 58. 54.100
libavformat    58. 29.100 / 58. 29.100
libavdevice    58.  8.100 / 58.  8.100
libavfilter     7. 57.100 /  7. 57.100
libswscale      5.  5.100 /  5.  5.100
libswresample   3.  5.100 /  3.  5.100
libpostproc    55.  5.100 / 55.  5.100
然后再去试试,对于srt,直接内嵌 烧录burn 硬字幕:
ffmpeg -i input/5d41d82f52247ce73d40475b_extendedAll.mp4 -vf subtitles=input/5d41d82f52247ce73d40475b.srt output/5d41d82f52247ce73d40475b_addedSrt.mp4
开始处理:
ffmpeg -i input/5d41d82f52247ce73d40475b_extendedAll.mp4 -vf subtitles=input/5d41d82f52247ce73d40475b.srt output/5d41d82f52247ce73d40475b_addedSrt.mp4
ffmpeg version 4.2-tessus  ...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input/5d41d82f52247ce73d40475b_extendedAll.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
  Duration: 00:02:15.05, start: 0.000000, bitrate: 758 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 700x510 [SAR 1:1 DAR 70:51], 622 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
[Parsed_subtitles_0 @ 0x7faf85508740] Shaper: FriBidi 0.19.2 (SIMPLE)
[Parsed_subtitles_0 @ 0x7faf85508740] Using font provider coretext
[libx264 @ 0x7faf87009400] using SAR=1/1
[libx264 @ 0x7faf87009400] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 0x7faf87009400] profile Progressive High, level 3.0, 4:2:0, 8-bit
[libx264 @ 0x7faf87009400] 264 - core 157 r2969 d4099dd - H.264/MPEG-4 AVC codec - Copyleft 2003-2019 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'output/5d41d82f52247ce73d40475b_addedSrt.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
    Stream #0:0(und): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 700x510 [SAR 1:1 DAR 70:51], q=-1--1, 25 fps, 12800 tbn, 25 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc58.54.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      encoder         : Lavc58.54.100 aac
[Parsed_subtitles_0 @ 0x7faf85508740] fontselect: (Arial, 400, 0) -> /Library/Fonts/Arial.ttf, -1, ArialMT
[Parsed_subtitles_0 @ 0x7faf85508740] Glyph 0x6211 not found, selecting one more font for (Arial, 400, 0)
[Parsed_subtitles_0 @ 0x7faf85508740] fontselect: (Arial, 400, 0) -> /System/Library/Fonts/PingFang.ttc, -1, PingFangSC-Regular
frame= 3376 fps= 71 q=-1.0 Lsize=   12188kB time=00:02:15.02 bitrate= 739.4kbits/s speed=2.84x    
video:9952kB audio:2124kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.918402%
[libx264 @ 0x7faf87009400] frame I:17    Avg QP:17.22  size: 38148
[libx264 @ 0x7faf87009400] frame P:1135  Avg QP:21.74  size:  6722
[libx264 @ 0x7faf87009400] frame B:2224  Avg QP:23.31  size:   860
[libx264 @ 0x7faf87009400] consecutive B-frames:  3.7% 21.7% 11.2% 63.4%
[libx264 @ 0x7faf87009400] mb I  I16..4: 35.1% 36.3% 28.6%
[libx264 @ 0x7faf87009400] mb P  I16..4:  6.6%  7.4%  1.9%  P16..4: 21.8%  6.3%  2.7%  0.0%  0.0%    skip:53.5%
[libx264 @ 0x7faf87009400] mb B  I16..4:  0.5%  0.5%  0.1%  B16..8: 15.2%  1.3%  0.2%  direct: 1.3%  skip:80.8%  L0:45.8% L1:50.3% BI: 3.9%
[libx264 @ 0x7faf87009400] 8x8 transform intra:45.6% inter:68.9%
[libx264 @ 0x7faf87009400] coded y,uvDC,uvAC intra: 31.4% 69.8% 38.1% inter: 5.4% 11.5% 2.4%
[libx264 @ 0x7faf87009400] i16 v,h,dc,p: 40% 47%  4%  9%
[libx264 @ 0x7faf87009400] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 29% 26% 24%  3%  3%  4%  4%  3%  4%
[libx264 @ 0x7faf87009400] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 31% 33% 14%  2%  4%  4%  5%  3%  3%
[libx264 @ 0x7faf87009400] i8c dc,h,v,p: 28% 38% 22% 11%
[libx264 @ 0x7faf87009400] Weighted P-Frames: Y:1.7% UV:1.2%
[libx264 @ 0x7faf87009400] ref P L0: 68.1% 17.0% 11.2%  3.7%  0.0%
[libx264 @ 0x7faf87009400] ref B L0: 87.7% 10.2%  2.1%
[libx264 @ 0x7faf87009400] ref B L1: 98.2%  1.8%
[libx264 @ 0x7faf87009400] kb/s:603.70
[aac @ 0x7faf86802e00] Qavg: 214.622
结果:
基本满足要求的
那再去试试ass字幕
先去从srt转换出ass
ffmpeg -i input/5d41d82f52247ce73d40475b.srt output/5d41d82f52247ce73d40475b.ass
结果:
ffmpeg -i input/5d41d82f52247ce73d40475b.srt output/5d41d82f52247ce73d40475b.ass
ffmpeg version 4.2-tessus  ...
Input #0, srt, from 'input/5d41d82f52247ce73d40475b.srt':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Subtitle: subrip
Output #0, ass, to 'output/5d41d82f52247ce73d40475b.ass':
  Metadata:
    encoder         : Lavf58.29.100
    Stream #0:0: Subtitle: ass (ssa)
    Metadata:
      encoder         : Lavc58.54.100 ssa
Stream mapping:
  Stream #0:0 -> #0:0 (subrip (srt) -> ass (ssa))
Press [q] to stop, [?] for help
size=       3kB time=00:02:04.21 bitrate=   0.2kbits/s speed=1.21e+05x    
video:0kB audio:0kB subtitle:2kB other streams:0kB global headers:1kB muxing overhead: 44.561996%
输出ass字幕
[Script Info]
; Script generated by FFmpeg/Lavc58.54.100
ScriptType: v4.00+
PlayResX: 384
PlayResY: 288

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding

Style: Default,Arial,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,1,0,2,10,10,10,0

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

Dialogue: 0,0:00:02.68,0:00:09.16,Default,,0,0,0,,I'm a policeman in the town. All day long,I walk around!\N我是镇上的警察 整天都在巡视
Dialogue: 0,0:00:09.18,0:00:15.86,Default,,0,0,0,,I'm a policeman in the town. All day long, I walk around!\N我是镇上的警察 整天都在巡视
...
然后再去嵌入ass字幕:
ffmpeg -i input/5d41d82f52247ce73d40475b_extendedAll.mp4 -vf "ass=output/5d41d82f52247ce73d40475b.ass" output/5d41d82f52247ce73d40475b_addedAss.mp4
结果:
效果是一样的。
然后再去看看,能否指定字幕显示位置:
【已解决】嵌入ASS字幕到mp4视频中如何指定字幕的位置
【总结】
此处,通过ffmpeg合并嵌入字幕到视频下方的具体步骤是:
需求1:如果无需操心字幕的具体位置,只需要保证字幕在视频底部
则可以直接嵌入字幕即可
其中字幕文件是srt或ass均可:
ffmpeg -i input/5d41d82f52247ce73d40475b_extendedAll.mp4 -vf subtitles=input/5d41d82f52247ce73d40475b.srt output/5d41d82f52247ce73d40475b_addedSrt.mp4
需求2:如果想要指定字幕的具体位置
那么先把srt文件(不支持字幕位置指定)转换为ass(可以指定字幕位置)
ffmpeg -i input/5d41d82f52247ce73d40475b.srt output/5d41d82f52247ce73d40475b.ass
再去嵌入ass字幕到视频中:
ffmpeg -i input/5d41d82f52247ce73d40475b_extendedAll.mp4 -vf "ass=output/5d41d82f52247ce73d40475b.ass" output/5d41d82f52247ce73d40475b_addedAss.mp4
其中:
字幕文件ass中,有对应的位置的参数配置
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding

Style: Default,Arial,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,1,0,2,10,10,10,0
其中:
  • Alignment:默认为2,就是底部居中
    • 就满足了我们希望的:字幕在底部居中的位置
此时再去微调左右间距和底部间距时,再去改动:
MarginL, MarginR, MarginV
即可,比如:
MarginL, MarginR, MarginV
20,20,10
即可实现:
  • MarginL=MarginR:左右间距20
  • MarginV:底部向上间距10

转载请注明:在路上 » 【已解决】ffmpeg合并字幕到视频下方指定位置

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
91 queries in 0.184 seconds, using 23.37MB memory