瞬息 电光石火、转瞬即逝

FFmpeg 给视频嵌入字幕

2022-07-22
Ko_teiru


如何把 ass 的字幕嵌入(硬嵌)视频中呢?用 Pr?还是小丸?

特效字幕又如何保留原始字体和特效嵌入呢?

就让小编来告诉你们吧~

大致流程

懒得看的直接跳到后面代码部分即可

首先,一般的普通对话字幕我直接使用的格式工厂,不过这玩意的字体和字体样式要自己设计,而且只能指定一种样式,所以这是最不理想的嵌字方式。

后面又尝试使用视频剪辑软件啥的,不过效果终究还是不太好。后面在查资料的时候看见了这么一篇文章:

虽然字幕流是一个很方便的东西,但是由于一些差的播放器不支持字幕流,字幕流也的显示也取决于播放器所使用的字体,所以在很多时候,我们需要将字幕放到视频内容中,而不是独立于视频流的字幕流。

  • 注意: 因为这样做会改写视频流,所以原本视频中被字幕覆盖的地方就无法再被显示出来了。

By: convert-videos-with-ffmpeg-zh,字幕章节

卧槽,这不就是咱想要的效果吗?火速研究一下,然后看见同教程下的另一条提示:

注意: 如果你使用的是遭天谴的 Microsoft Windows , FFmpeg 会在写视频流的时候无法找到字体,而导致输出文件中没有任何字幕,要解决这个问题,请参阅这篇文章

哈哈哈哈,正好我也是 windows,所以也必须读一下那篇文章了,不过这篇文章在盘符路径存在 C:\\c:\ 混用的情况,经测试两个都是可以正常使用的,没关系。

这下我们就可以通过 FFmpeg 对番啊什么的嵌入字幕了,是不是很简单?

当然不是,如果要一行行指令敲的话那也太傻逼慢了吧?想起来之前有给超分图片写的一个 bat 批处理文件,刚觉正好可以拿来改改,毕竟都是指令行的形式运行的嘛。

不过想得很美好,真正改起来就出问题了,在 subtitles="C:xxxx\xxxxx\xxxx.ass" 时就一直报错,不过哥们一贯的面向搜索引擎编程,不一会就找到解决办法了。

简而言之就是 subtitles= 的值被二次分解导致 : \ " 等符号被和谐了。解决方法来自:IPBStoryParserffmpeg合并字幕文件出现错误的解决办法

转变为 bat 大致可以写成

set /p sub=请拖入字幕文件:
setlocal enabledelayedexpansion
set "sub=!sub:\=\\!"
set "sub=!sub:"='!"
set "sub=!sub::\\=\:\\!"
set sub="%sub%"
endlocal

首先把所有的单反斜杠替换成双反斜杠,再把半角双引号替换成单引号,再在盘符处给引号再加一个反斜杠,最后再给开头和结尾套一层双引号,大功告成~

然后用这文件处理了几部番没啥问题,不过后面某一部番却老报错,判断问题出在这里:

if %file% neq %file: =% (
    set s1=包含空格
) else (
    set s1=不包含空格
    set file="%file%"
    rem 就是上面这行
)

原理不清楚,这个判断的本意是用来检测输入路径是否带空格的。如果是带空格的文件路径,windows 会给你套一层双引号,一般直接跳过 else 就行了。不过再某些情况下这里会报错“这里不应该存在 XXX”,所以就很苦恼,找半天原因也没搞懂,后面直接想着不给 set 写进 if 语句里了,直接用 goto 规避一下,结果倒是不会报错了。反正能用就行,不是吗。

set /p sub=请拖入字幕文件:
if %sub% neq %sub: =% (
    set s2=包含空格
    rem 因为包含空格=包含引号,所以直接跳到 set 的后面去
    goto y
) else (
    set s2=不包含空格
)
set sub="%sub%"

:y
echo 字幕文件%s2% 

代码

至此,脚本基本没啥问题了。全部代码如下,丢 FFmpeg.exe 所在的目录改成 .bat 的文件,并且创建桌面快捷方式,保存格式选 GBK 喵。

要使用的话直接把视频文件拖到快捷方式的图标上打开,再把字幕文件拖上去敲一下回车即可~

批处理结束之后窗口会变蓝,假如窗口直接变蓝了说明报错了。自己 debug 吧。

另外视频码率默认是 5Mbps,根据自己需求更改即可。如果是要处理电影的话可以拉高一点,比如15或者50(越高视频会越大)

@echo off
title 这里是标题daze~
color 02
rem 请手动设置码率 默认 5M(5000)
set M=5M
set file=%1
rem 判断路径是否包含空格
if %file% neq %file: =% (
    set s1=包含空格
    goto x
    rem 跳过
) else (
    set s1=不包含空格
)
set file="%file%"

:x
echo 视频路径 %s1%
echo.
set n=H264
set o=%file:~0,-5%
set tpye=.mp4"
set o=%o%-%n%%tpye%
echo 请拖入字幕文件并按回车(如果有)
set /p sub=^>
rem 判断是否输入字幕文件
if [%sub%] == [] (
    goto z
)
rem 判断路径是否包含空格
if %sub% neq %sub: =% (
    set s2=包含空格
    goto y
) else (
    set s2=不包含空格
)
set sub="%sub%"

:y
echo 字幕路径 %s2%
SETLOCAL EnableDelayedExpansion
set "sub=!sub:\=\\!"
set "sub=!sub:"='!"
set "sub=!sub::\\=\:\\!"
set sub="%sub%"
.\ffmpeg -hwaccel cuda -i %file% -c:a copy -c:v h264_nvenc -pix_fmt yuv420p -b:v %M% -bufsize %M% -strict -2 -vf subtitles=%sub% %o%
goto end

:z
.\ffmpeg.exe -hwaccel cuda -i %file% -c:a copy -c:v h264_nvenc -pix_fmt yuv420p -b:v %M% -bufsize %M% -strict -2 %o%

:end
color 3F
pause

需要注意的是,这个文件只适用于支持 cuda 的 N 卡用户将 H.265 的视频嵌入字幕并转换为 H.264 时使用。

如果你没有这个需求,请不要使用或者自行修改代码。

参数解释

%file% 是经过处理的输入视频路径,它始终保持被引号包围的情况

%sub% 是经过处理的字幕文件所在的路径,它是经过转意处理的路径,应该不会出错

%n% 是自定义的一个值,它会被加入输出文件名用作区分,你可以使用 date 当作这个值

%type% 是遗留下来的一个获取文件类型的蠢方法,它用切割字符串的方式获取路径后 5 个字符。例如 .mp4" 这里是写死的 .mp4",你可以自行修改

%M% 是视频码率和倾向码率的值,单位为 Mbps,请根据自身需求更改

%o% 是输出位置,它与输入路径相同,但会在原本文件名的基础上加上 %n% 名,并修改后缀为 %type%

其他关于 FFmpeg 的参数可以自行百度或修改成自己所需要的。

碎碎念

关于字幕和字体的相关,MKV 内封的花式字幕一般都会自带字体文件,而且有可能每集的字体文件的文件名还不同,你需要使用抽取工具把该集的字体文件收取出来再安装。这里推荐用小丸工具箱里 抽取 — 其他工具 来抽取,速度也很快就是了。

我的2060一次最多只能开三个处理,多了就报错了,显卡体制不能一概而论,还请根据实际调整。


前一篇 scala 相关

评论

折跃门