Python結(jié)合FFmpeg實(shí)現(xiàn)為視頻添加內(nèi)嵌字幕SRT的完整教程
摘要
本文介紹如何使用 Python 調(diào)用 FFmpeg,將 視頻文件(MP4)與字幕文件(SRT)進(jìn)行無損合并,并輸出帶字幕的新視頻。文中提供了完整可運(yùn)行的 Python 腳本,包括文件校驗(yàn)、FFmpeg 調(diào)用、錯(cuò)誤處理等。適用于想要批量合并視頻 + 字幕、制作教學(xué)視頻、課程字幕嵌入等場(chǎng)景。
一、背景需求
在視頻編輯、課程制作、影視處理等場(chǎng)景中,我們經(jīng)常需要:
- 下載的視頻沒有內(nèi)嵌字幕
- 手里有
.srt字幕文件 - 需要把字幕“封裝”到
.mp4里(但不燒錄,只是內(nèi)封)
使用 FFmpeg 可以輕松做到,而 Python 則可以讓流程自動(dòng)化、批量化。
二、實(shí)現(xiàn)原理
FFmpeg 提供了豐富的視頻/音頻/字幕處理功能,這里我們用到:
ffmpeg -i video.mp4 -i subtitle.srt -c:v copy -c:a copy -c:s mov_text output.mp4
說明:
-c:v copy:不重新編碼視頻(無損、快速)-c:a copy:不重新編碼音頻-c:s mov_text:將 SRT 封裝為 MP4 支持的字幕格式- 使用 Python 的
subprocess.run()調(diào)用 FFmpeg
三、依賴環(huán)境
你的系統(tǒng)需要安裝:
- Python 3.x
- FFmpeg(必需)
檢查 FFmpeg 是否安裝:
ffmpeg -version
沒有安裝請(qǐng)到官網(wǎng)或使用包管理工具安裝。
四、完整 Python 代碼(含中文注釋)
下面是可直接運(yùn)行的腳本,已加上完整中文說明,適合新手和入門 FFmpeg/Python 的讀者:
import subprocess
import os
import sys
def validate_file(file_path, file_type="file"):
"""驗(yàn)證文件是否存在"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"{file_type.capitalize()} 文件不存在: {file_path}")
print(f"{file_type.capitalize()} 已驗(yàn)證: {file_path}")
return True
def merge_video_with_subtitles(video_path, srt_path, output_path):
"""使用 FFmpeg 將視頻與 SRT 字幕合并"""
# 1. 驗(yàn)證輸入文件
validate_file(video_path, "video")
validate_file(srt_path, "subtitle")
# 2. FFmpeg 指令
ffmpeg_cmd = [
'ffmpeg',
'-i', video_path, # 輸入視頻
'-i', srt_path, # 輸入字幕
'-c:v', 'copy', # 視頻無損copy
'-c:a', 'copy', # 音頻無損copy
'-c:s', 'mov_text', # 字幕轉(zhuǎn)換為 mp4 可識(shí)別格式
'-metadata:s:s:0', 'language=chi', # 字幕語言設(shè)置為中文
output_path
]
# 強(qiáng)制字幕按 UTF-8 解碼(避免亂碼)
ffmpeg_cmd.insert(3, '-sub_charenc')
ffmpeg_cmd.insert(4, 'UTF-8')
try:
# 3. 調(diào)用 FFmpeg 進(jìn)行處理
result = subprocess.run(
ffmpeg_cmd,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
print(f"成功生成視頻: {output_path}")
print(result.stdout)
except subprocess.CalledProcessError as e:
print(f"FFmpeg 處理失敗: {e.stderr}")
raise
except Exception as e:
print(f"運(yùn)行 FFmpeg 時(shí)發(fā)生異常: {e}")
raise
def main():
# 輸入文件路徑(可自行修改)
video_path = r"SS.online_Gesture Drawing Practice _ 20 and 40 sec. poses_1080p.mp4"
srt_path = r"SS.online_Gesture Drawing Practice _ 20 and 40 sec. poses_1080p.srt"
output_path = "output.mp4"
# 合并視頻 + 字幕
merge_video_with_subtitles(video_path, srt_path, output_path)
if __name__ == "__main__":
try:
main()
except Exception as e:
print(f"程序錯(cuò)誤: {e}")
sys.exit(1)
五、運(yùn)行方式
直接:
python merge.py
執(zhí)行完成后,將生成:
output.mp4
用任意播放器(如 VLC)打開 → 字幕即可選擇顯示。
六、說明與注意事項(xiàng)
1. 字幕不會(huì)“燒錄”
此方法是 內(nèi)封字幕(soft subtitle),播放器可以選擇開啟/關(guān)閉。
2. 字幕亂碼?
可嘗試:
-sub_charenc UTF-8
代碼中已自動(dòng)加入該選項(xiàng)。
3. 多字幕?
支持??蓴U(kuò)展代碼進(jìn)行批量字幕封裝。
4. 輸出文件不會(huì)重新壓制視頻
因?yàn)椋?/p>
-c:v copy -c:a copy
速度極快(幾秒內(nèi)完成)。
七、知識(shí)擴(kuò)展
Python實(shí)現(xiàn)json字幕轉(zhuǎn)換為srt字幕
在B站下載了一個(gè)英文視頻,點(diǎn)開來看,發(fā)現(xiàn)沒有字幕,又在B站上下了字幕,是json格式的,但我的PotPlayer不支持json格式的字幕,頓時(shí)感覺被坑了,上網(wǎng)搜了搜json字幕轉(zhuǎn)換其他字幕格式的工具,結(jié)果并沒有這種東西,倒是找到了一篇srt字幕轉(zhuǎn)json字幕的博客,反正閑著沒事,我就參照著這篇博客用python寫了個(gè)將json字幕轉(zhuǎn)換為srt字幕的腳本。
先看看json字幕的格式:

from為開始時(shí)間,to為結(jié)束時(shí)間,location是位置,content是字幕內(nèi)容。
再看看srt字幕的格式:

首先第一行是序號(hào),第二行是開始時(shí)間(時(shí):分:秒,小數(shù)位,如00:00:02,81就是2.81秒)和終止時(shí)間,第三行是字幕文字,后面一定要加上一個(gè)空行。
所以我們要做的工作主要就是把json文件的時(shí)間格式轉(zhuǎn)換為srt文件的時(shí)間格式,另外再把字幕和序號(hào)添加上就可以了。
把該程序文件和json字幕文件放在同一文件夾下,運(yùn)行此程序即可。
代碼如下:
import json
import math
import os
for doc in os.listdir(): # 遍歷當(dāng)前文件夾的所有文件
file = '' # 這個(gè)變量用來保存數(shù)據(jù)
i = 1
if (doc[-4:] == 'json'): # 若是json文件則進(jìn)行處理
name = doc[:-5] # 提取文件名
# 將此處文件位置進(jìn)行修改,加上utf-8是為了避免處理中文時(shí)報(bào)錯(cuò)
with open(doc, encoding='utf-8') as f:
datas = json.load(f) # 加載文件數(shù)據(jù)
f.close()
for data in datas:
start = data['from'] # 獲取開始時(shí)間
stop = data['to'] # 獲取結(jié)束時(shí)間
content = data['content'] # 獲取字幕內(nèi)容
file += '{}\n'.format(i) # 加入序號(hào)
hour = math.floor(start) // 3600
minute = (math.floor(start) - hour * 3600) // 60
sec = math.floor(start) - hour * 3600 - minute * 60
minisec = int(math.modf(start)[0] * 100) # 處理開始時(shí)間
file += str(hour).zfill(2) + ':' + str(minute).zfill(2) + ':' + str(sec).zfill(2) + ',' + str(minisec).zfill(2) # 將數(shù)字填充0并按照格式寫入
file += ' --> '
hour = math.floor(stop) // 3600
minute = (math.floor(stop) - hour * 3600) // 60
sec = math.floor(stop) - hour * 3600 - minute * 60
minisec = abs(int(math.modf(stop)[0] * 100 - 1)) # 此處減1是為了防止兩個(gè)字幕同時(shí)出現(xiàn)
file += str(hour).zfill(2) + ':' + str(minute).zfill(2) + ':' + str(sec).zfill(2) + ',' + str(minisec).zfill(2)
file += '\n' + content + '\n\n' # 加入字幕文字
i += 1
with open('./{}.srt'.format(name), 'w', encoding='utf-8') as f:
f.write(file) # 將數(shù)據(jù)寫入文件
f.close()最后得到的srt文件如圖所示:

到此這篇關(guān)于Python結(jié)合FFmpeg實(shí)現(xiàn)為視頻添加內(nèi)嵌字幕SRT的完整教程的文章就介紹到這了,更多相關(guān)Python FFmpeg視頻添加字幕內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用numba對(duì)Python運(yùn)算加速的方法
今天小編就為大家分享一篇使用numba對(duì)Python運(yùn)算加速的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-10-10
教你在Excel中調(diào)用Python腳本實(shí)現(xiàn)數(shù)據(jù)自動(dòng)化處理的方法
Excel是全世界最流行的編程語言,Excel已經(jīng)可以實(shí)現(xiàn)編程語言的算法,因此它是具備圖靈完備性的,和JavaScript、Java、Python一樣,今天通過本文給大家介紹下Python數(shù)據(jù)自動(dòng)化處理的相關(guān)知識(shí),感興趣的朋友一起看看吧2022-02-02
Python使用PyMuPDF實(shí)現(xiàn)添加PDF水印
在日常工作中,我們經(jīng)常需要對(duì)PDF文件進(jìn)行處理,其中一項(xiàng)常見的需求是向PDF文件添加水印,本文將介紹如何使用Python編程語言和PyMuPDF庫在PDF文件中添加水印,感興趣的可以了解一下2023-08-08
Python使用openpyxl批量處理數(shù)據(jù)
openpyxl 是一個(gè)用于處理 xlsx 格式Excel表格文件的第三方python庫,其支持Excel表格絕大多數(shù)基本操作。本文給大家介紹Python使用openpyxl批量處理數(shù)據(jù)的操作方法,感興趣的朋友一起看看吧2021-06-06
python多進(jìn)程 主進(jìn)程和子進(jìn)程間共享和不共享全局變量實(shí)例
這篇文章主要介紹了python多進(jìn)程 主進(jìn)程和子進(jìn)程間共享和不共享全局變量實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04
如何基于Python pygame實(shí)現(xiàn)動(dòng)畫跑馬燈
這篇文章主要介紹了如何基于Python pygame實(shí)現(xiàn)動(dòng)畫跑馬燈,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11

