使用 FFmpeg 删除导出视频字幕文件
Posted 小工具代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用 FFmpeg 删除导出视频字幕文件相关的知识,希望对你有一定的参考价值。
大家好,我是青空。
前些天看到一个群里有人在问,有没有办法把视频中的字幕删除掉。我想了想,可以使用FFmpeg 这个软件来处理。该方法适用于视频中的软字幕,就是平常我们做视频在剪映类似软件上自己加上去的字幕。
下载FFmpeg for Windows
步骤
- 下载 FFmpeg https://www.ffmpeg.org/download.html
- 解压缩并保存到C盘(选择任何位置)。
- 设置环境变量 – 复制解压文件中 bin 文件夹的位置,并在系统路径变量中设置该位置。
删除软字幕
假设你有一个名为 demo.mkv 的视频文件,内置的字幕是你不需要的, 那我们可以使用 ffmpeg 框架简单地删除字幕。我们说的是内置字幕,而不是.srt文件。步骤如下
- 转到你的文件位置,在那里打开命令提示符或终端。
- 之后,运行以下命令
ffmpeg -i video.mkv -vcodec copy -acodec copy -sn video-no-subs.mkv
整合软字幕
现在,如果你想在视频上整合一个srt文件。步骤如下
- 从网上下载想要的字幕。
- 我们假设Demo.mkv和下载的文件名为sub.srt
- 把这两个文件放在一个地方,然后从这个地方打开终端,运行以下命令
- 首先将字幕转换成.ass格式:
ffmpeg -i sub.srt subs.ass
- 要将字幕混入视频文件,运行
- 首先将字幕转换成.ass格式:
ffmpeg -i demo.mkv -i sub.ass -codec copy -map 0 -map 1 output.mkv
为视频文件提取字幕
在这种情况下,一个视频文件中嵌入了字幕,你想把它变成srt文件或其他工作的软字幕文件。我们可以通过以下命令来做
ffmpeg -i demo.mkv -map 0:s:0 sub.srt
总结
该方法适用于软字幕,下次直接做个软件来执行这个命令行,有需求的可以留言或者加我微信,空了可以做一个。
如何映射用ffmpeg和视频字幕提取的帧? (帧精度问题)
【中文标题】如何映射用ffmpeg和视频字幕提取的帧? (帧精度问题)【英文标题】:How to map frame extracted with ffmpeg and subtitle of a video? (frame accuracy problem) 【发布时间】:2019-11-12 15:12:09 【问题描述】:想为使用 ffmpeg 提取的帧生成文本文件,如果有的话,包含帧的字幕,在我也使用 ffmpeg 刻录字幕的视频上。
我使用带有pysrt
的python 脚本来打开subrip 文件并生成文本文件。
我正在做的是每个帧都由 ffmpeg 用帧号命名,然后由于它们以恒定速率提取,我可以使用公式 t1 = fnum/fps
轻松检索帧的时间位置,其中fnum
是使用文件名检索的帧数,fps
是传递给 ffmpeg 以进行帧提取的频率。
即使我使用相同的字幕文件来检索时间轴中的文本位置,也就是视频中使用的那个,我仍然会遇到准确性错误。大多数我有一些文本文件丢失或一些不应该存在。
因为在谈论帧时时间并不是真正连续的,所以我尝试使用带有硬编码字幕的视频的 fps 重新校准 t
,让我们将 fps vfps
称为视频 fps(我已确保视频 fps字幕刻录前后相同)。我得到公式:t2 = int(t1*vfps)/vfps
。
它仍然不是 100% 准确。
例如,我的视频是 30fps (vfps=30
),我以 4fps (fps=4
) 提取帧。
提取的第 166 帧 (fnum=166
) 没有显示字幕。在 subrip 文件中,前一个字幕以t_prev=41.330
结尾,下一个字幕从t_next=41.400
开始,这意味着t_sub
应该满足:t_prev < t_sub and t_sub < t_next
,但我无法做到这一点。
我试过的公式:
t1 = fnum/fps # 41.5 > t_next
t2 = int(fnum*vfps/fps)/vfps # 41.5 > t_next
# is it because of a indexing problem? No:
t3 = (fnum-1)/fps # 41.25 < t_prev
t4 = int((fnum-1)*vfps/fps)/vfps # 41.23333333 < t_prev
t5 = int(fnum*vfps/fps - 1)/vfps # 41.466666 > t_next
t6 = int((fnum-1)*vfps/fps + 1)/vfps # 41.26666 < t_prev
使用的命令:
# burning subtitles
# (previously)
# ffmpeg -r 25 -i nosub.mp4 -vf subtitles=sub.srt withsub.mp4
# now:
ffmpeg -i nosub.mp4 -vf subtitles=sub.srt withsub.mp4
# frames extraction
ffmpeg -i withsub.mp4 -vf fps=4 extracted/%05.bmp -hide_banner
为什么会发生这种情况,我该如何解决?
我注意到的一件事是,如果我提取原始视频和字幕的帧,对帧进行差异处理,结果不仅是字幕,背景也有变化(这不应该发生)。如果我两次使用相同的视频做相同的体验,差异为null,这意味着帧提取是一致的。
区别代码:
ffmpeg -i withsub.mp4 -vf fps=4 extracted/%05.bmp -hide_banner
ffmpeg -i no_sub.mp4 -vf fps=4 extracted_no_sub/%05.bmp -hide_banner
for img in no_sub/*.bmp; do
convert extracted/$img##*/ $img -compose minus -composite diff/$img##*/
done
谢谢。
【问题讨论】:
ffmpeg -r 25 -i nosub.mp4 --> 这将重新定时帧并破坏原始时间戳。除非您知道自己在做什么,否则您不想这样做。 不是真的...我想在不改变帧率的情况下刻录字幕。所以我先试试这个:ffmpeg -i nosub.mp4 -vf subtitles=sub.srt withsub.mp4
但是它把帧率从25改成了30,所以我手动设置了帧率,好像不对。我不是 ffmpeg 的大用户。我在 Google 上搜索了如何使用 ffmpeg 保留帧率并找到了这个 superuser.com/questions/460332/…,但它没有被接受的答案。
分享您最初尝试的日志。
我的错,原来的 fps 是 30,所以我第一次尝试刻录字幕并没有改变帧速率。然而问题依然存在。并且在字幕刻录前后进行帧减法显示出比字幕更多的差异。请让我提醒一下,这不是我要解决的问题,但可能是我的问题的原因。你想看什么日志?
还值得注意的是,在示例中,区间的边界乘以帧提取得到:t_prev*fps=165.32
和 t_next*fps=165.6
,这意味着,如果 ffmpeg 提取的帧是1/fps
的因素,那么我不应该让第 166 帧位于两个字幕之间,而是显示第二个字幕(或者前一个字幕)。如果通过视频 fps 进行校正也是一样的:int(t_next*vfps)*fps/vfps=165.2
, int(t_next*vfps)*fps/vfps=165.6
【参考方案1】:
您可以提取具有准确时间戳的帧,因此
ffmpeg -i nosub.mp4 -vf subtitles=sub.srt,settb=AVTB,select='if(eq(n\,0)\,1\,floor(4*t)-floor(4*prev_t))' -vsync 0 -r 1000 -frame_pts true extracted/%08d.bmp
这将从每四分之一秒中提取第一帧。输出文件名长度为 8 个字符,其中前 5 位是秒,后三位是毫秒。您可以根据最大文件持续时间更改字段大小。
【讨论】:
您能否详细介绍一下参数?我也收到一个错误:Missing ')' or too many args in 'if(eq(n,0)'
settb 过滤器用于将时基设置为 1 微秒,选择过滤器表达式将选择第一帧,然后选择最接近上一季度秒的每一帧。 -r 1000 将时间戳转换为毫秒精度(否则文件名会变得更长)。 vsync 确保 ffmpeg 不会改变时间戳。 frame_pts 将时间戳打印到文件名中。
编辑 cmd 以转义所有逗号以上是关于使用 FFmpeg 删除导出视频字幕文件的主要内容,如果未能解决你的问题,请参考以下文章
android 中使用ffmpeg,将视频加入字幕,用ass文件,在PC上可以,但在Android上一直不行