基于Python實(shí)現(xiàn)視頻和音頻長度對齊合成并添加字幕功能
環(huán)境設(shè)置
首先,我們需要安裝必要的庫??梢允褂靡韵旅顏戆惭b它們:
pip install opencv-python moviepy Pillow
準(zhǔn)備工作
- 準(zhǔn)備音頻和視頻文件:確保你有需要對齊的音頻和視頻文件。
- 下載支持中文的字體文件:例如SimHei.ttf,并將其保存到合適的位置。在示例中,我們使用NotoSansCJKsc-Regular.ttf。
實(shí)現(xiàn)代碼
以下是實(shí)現(xiàn)音視頻對齊并添加中文字幕的完整Python代碼。你可以將這段代碼保存為一個Python文件,并根據(jù)需要進(jìn)行調(diào)用。
import cv2
import numpy as np
from moviepy.editor import AudioFileClip, VideoFileClip
from pydub import AudioSegment
from PIL import Image, ImageDraw, ImageFont
import tempfile
import os
import re
def replace_punctuation_with_at(input_string):
# 使用正則表達(dá)式匹配所有標(biāo)點(diǎn)符號并替換為 @
result = re.sub(r'[^\w\s]', '@', input_string)
return result
def add_chinese_subtitle_to_frame(frame, subtitle_text, position, font_path, font_size, font_color):
# 將OpenCV圖像轉(zhuǎn)換為PIL圖像
img_pil = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_pil)
font = ImageFont.truetype(font_path, font_size)
# 獲取字幕文本的寬度和高度
text_bbox = draw.textbbox((0, 0), subtitle_text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
# 計算字幕的放置位置
x = position[0] - text_width // 2
y = position[1] - text_height // 2
# 在PIL圖像上添加字幕
draw.text((x, y), subtitle_text, font=font, fill=font_color)
# 將PIL圖像轉(zhuǎn)換回OpenCV圖像
frame = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
return frame
def sync_audio_video_add_subtitle(audio_path, video_path, output_path, subtitle_text, font_path, font_size=24, font_color=(255, 255, 255), subtitle_bottom_margin=30, audio_volume=1.0):
# 加載音頻文件并調(diào)整音量
original_audio = AudioSegment.from_file(audio_path)
original_audio = original_audio + (audio_volume * 10 - 10) # 調(diào)整音量
silence = AudioSegment.silent(duration=500) # 0.5秒的靜音
audio_with_silence = silence + original_audio + silence
# 創(chuàng)建臨時文件以保存修改后的音頻
temp_audio_path = os.path.join(tempfile.gettempdir(), "temp_audio.mp3")
audio_with_silence.export(temp_audio_path, format="mp3")
# 加載修改后的音頻文件
audio_clip = AudioFileClip(temp_audio_path)
audio_duration = audio_clip.duration
# 加載視頻文件
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
video_duration = frame_count / fps
# 計算新的視頻幀率
new_fps = fps * (video_duration / audio_duration)
# 獲取視頻尺寸
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 創(chuàng)建臨時文件以存儲中間視頻結(jié)果
temp_video_path = os.path.join(tempfile.gettempdir(), "temp_video.mp4")
# 創(chuàng)建VideoWriter對象
out = cv2.VideoWriter(temp_video_path, cv2.VideoWriter_fourcc(*'mp4v'), new_fps, (width, height))
# 分批讀取和寫入視頻幀,并添加字幕
subtitle_text = replace_punctuation_with_at(subtitle_text)
subtitle_text_list = [text for text in subtitle_text.split("@") if text]
print(subtitle_text_list)
subtitles_per_frame = frame_count // len(subtitle_text_list)
current_subtitle_index = 0
for frame_idx in range(frame_count):
ret, frame = cap.read()
if not ret:
break
# 添加當(dāng)前字幕到幀
if frame_idx // subtitles_per_frame >= current_subtitle_index and current_subtitle_index < len(subtitle_text_list):
frame = add_chinese_subtitle_to_frame(frame, subtitle_text_list[current_subtitle_index], (width // 2, height - subtitle_bottom_margin), font_path, font_size, font_color)
if frame_idx // subtitles_per_frame > current_subtitle_index:
current_subtitle_index += 1
out.write(frame)
cap.release()
out.release()
# 使用MoviePy將音頻和調(diào)整后的視頻合并
video_clip = VideoFileClip(temp_video_path).set_duration(audio_duration)
final_clip = video_clip.set_audio(audio_clip)
# Trim the last 0.3 seconds
final_clip = final_clip.subclip(0, final_clip.duration - 0.3)
# Write the final video file
final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac")
# Close the clips to release the file
final_clip.close()
video_clip.close()
audio_clip.close()
# 刪除臨時文件
os.remove(temp_audio_path)
os.remove(temp_video_path)
if __name__ == "__main__":
# 示例用法
audio_path = r"C:\Users\60568\Pictures\create\屈原\mp3\00000002.mp3"
video_path = r"C:\Users\60568\Pictures\create\屈原\mp4\03.mp4"
subtitle_text='然而屈原的直言進(jìn)諫,引來了朝中權(quán)臣的嫉恨,他成為了政治斗爭的犧牲品。'
output_path = "synced_video.mp4"
sync_audio_video_add_subtitle(audio_path,
video_path,
output_path,
subtitle_text=subtitle_text,
font_path="./NotoSansCJKsc-Regular.ttf",
font_size=40, # 設(shè)置字體大小
font_color=(255, 255, 255), # 設(shè)置字體顏色
subtitle_bottom_margin=80, # 設(shè)置字幕底部的位置
audio_volume=2) # 調(diào)整音頻音量,1.0為原始音量,1.5為增加50%音量
代碼說明
- add_chinese_subtitle_to_frame: 這個函數(shù)將字幕添加到給定的幀上。它使用PIL庫來繪制字幕,然后將圖像轉(zhuǎn)換回OpenCV格式。
- sync_audio_video_add_subtitle: 這個函數(shù)處理音頻和視頻的對齊,并將字幕添加到每一幀上。最終,它將處理好的視頻和音頻合并,并生成輸出文件。
保證音頻長度不變,調(diào)整視頻長度
在此代碼中,我們特別強(qiáng)調(diào)了保證音頻長度不變,通過調(diào)整視頻的幀率來匹配音頻長度。這是通過計算新的幀率 new_fps 實(shí)現(xiàn)的:
new_fps = fps * (video_duration / audio_duration)
調(diào)整參數(shù)
你可以通過調(diào)整以下參數(shù)來修改字幕的顯示效果和位置:
font_size: 字體大小。font_color: 字體顏色。subtitle_bottom_margin: 字幕距離視頻底部的距離。
運(yùn)行示例
你可以使用提供的示例用法來運(yùn)行代碼,只需將audio_path、video_path和font_path替換為你自己的文件路徑即可。
通過這個教程,你應(yīng)該能夠使用Python輕松地實(shí)現(xiàn)視頻和音頻的對齊,并在視頻中添加中文字幕。
以上就是基于Python實(shí)現(xiàn)視頻和音頻長度對齊合成并添加字幕功能的詳細(xì)內(nèi)容,更多關(guān)于Python視頻和音頻對齊并添加字幕的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用 Python 快速實(shí)現(xiàn) HTTP 和 FTP 服務(wù)器的方法
這篇文章主要介紹了使用 Python 快速實(shí)現(xiàn) HTTP 和 FTP 服務(wù)器 的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07
Python命令行參數(shù)解析工具 docopt 安裝和應(yīng)用過程詳解
這篇文章主要介紹了Python命令行參數(shù)解析工具 docopt 安裝和應(yīng)用過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09
如何優(yōu)雅地改進(jìn)Django中的模板碎片緩存詳解
這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅地改進(jìn)Django中的模板碎片緩存的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
淺談python對象數(shù)據(jù)的讀寫權(quán)限
下面小編就為大家?guī)硪黄獪\談python對象數(shù)據(jù)的讀寫權(quán)限。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09
使用Python實(shí)現(xiàn)MP4轉(zhuǎn)GIF
在日常生活中,我們經(jīng)常會遇到需要將 MP4 文件轉(zhuǎn)換為 GIF 文件的需求,本文將介紹一種使用 Python 實(shí)現(xiàn) MP4 轉(zhuǎn) GIF 程序的方法,這種方法簡單易學(xué),而且完全免費(fèi),需要的可以參考下2023-12-12
OpenCV簡單標(biāo)準(zhǔn)數(shù)字識別的完整實(shí)例
這篇文章主要給大家介紹了關(guān)于OpenCV簡單標(biāo)準(zhǔn)數(shù)字識別的相關(guān)資料,要通過opencv 進(jìn)行數(shù)字識別離不開訓(xùn)練庫的支持,需要對目標(biāo)圖片進(jìn)行大量的訓(xùn)練,才能做到精準(zhǔn)的識別出目標(biāo)數(shù)字,需要的朋友可以參考下2021-09-09
pycharm 使用心得(六)進(jìn)行簡單的數(shù)據(jù)庫管理
功能簡介:pycharm自帶了一個簡單的數(shù)據(jù)庫插件,可以比較方便的進(jìn)行簡單的數(shù)據(jù)庫操作。2014-06-06
詳解python實(shí)現(xiàn)交叉驗(yàn)證法與留出法
這篇文章主要介紹了詳解python實(shí)現(xiàn)交叉驗(yàn)證法與留出法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07

