基于Python实现视频和音频长度对齐合成并添加字幕功能

Written by

in

文章目录
  • 首先,我们需要安装必要的库。可以使用以下命令来安装它们: pip install opencv-python moviepy Pillow
  • 准备音频和视频文件:确保你有需要对齐的音频和视频文件。 下载支持中文的字体文件:例如SimHei.ttf,并将其保存到合适的位置。在示例中,我们使用NotoSansCJKsc-Regular.ttf。
  • 以下是实现音视频对齐并添加中文字幕的完整Python代码。你可以将这段代码保存为一个Python文件,并根据需要进行调用。 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): # 使用正则表达式匹配所有标点符号并替换为 @ result = re.sub(r'[^ws]’, ‘@’, input_string) return result def add_chinese_subtitle_to_frame(frame, subtitle_text, position, font_path, font_size, font_color): # 将OpenCV图像转换为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图像转换回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): # 加载音频文件并调整音量 original_audio = AudioSegment.from_file(audio_path) original_audio = original_audio + (audio_volume * 10 – 10) # 调整音量 silence = AudioSegment.silent(duration=500) # 0.5秒的静音 audio_with_silence = silence + original_audio + silence # 创建临时文件以保存修改后的音频 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)) # 创建临时文件以存储中间视频结果 temp_video_path = os.path.join(tempfile.gettempdir(), “temp_video.mp4”) # 创建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 # 添加当前字幕到帧 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将音频和调整后的视频合并 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:Users60568Picturescreate屈原mp30000002.mp3″ video_path = r”C:Users60568Picturescreate屈原mp43.mp4″ subtitle_text=’然而屈原的直言进谏,引来了朝中权臣的嫉恨,他成为了政治斗争的牺牲品。’ 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, # 设置字体大小 font_color=(255, 255, 255), # 设置字体颜色 subtitle_bottom_margin=80, # 设置字幕底部的位置 audio_volume=2) # 调整音频音量,1.0为原始音量,1.5为增加50%音量
  • add_chinese_subtitle_to_frame: 这个函数将字幕添加到给定的帧上。它使用PIL库来绘制字幕,然后将图像转换回OpenCV格式。 sync_audio_video_add_subtitle: 这个函数处理音频和视频的对齐,并将字幕添加到每一帧上。最终,它将处理好的视频和音频合并,并生成输出文件。
  • 在此代码中,我们特别强调了保证音频长度不变,通过调整视频的帧率来匹配音频长度。这是通过计算新的帧率 new_fps 实现的: new_fps = fps * (video_duration / audio_duration)
  • 你可以通过调整以下参数来修改字幕的显示效果和位置: font_size: 字体大小。 font_color: 字体颜色。 subtitle_bottom_margin: 字幕距离视频底部的距离。
  • 你可以使用提供的示例用法来运行代码,只需将audio_path、video_path和font_path替换为你自己的文件路径即可。 通过这个教程,你应该能够使用Python轻松地实现视频和音频的对齐,并在视频中添加中文字幕。 以上就是基于Python实现视频和音频长度对齐合成并添加字幕功能的详细内容,更多关于Python视频和音频对齐并添加字幕的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: Python基于MoviePy实现一键提取视频音频并生成MP3 详解如何使用Python提取视频文件中的音频 Python脚本实现音频和视频格式转换 Python实现视频转换为音频的方法详解 python中视频音频的剪辑与处理实现
  • 目录
    • 环境设置
    • 准备工作
    • 实现代码
    • 代码说明
    • 保证音频长度不变,调整视频长度
    • 调整参数
    • 运行示例

    首先,我们需要安装必要的库。可以使用以下命令来安装它们:

    pip install opencv-python moviepy Pillow
    

    1. 准备音频和视频文件:确保你有需要对齐的音频和视频文件。
    2. 下载支持中文的字体文件:例如SimHei.ttf,并将其保存到合适的位置。在示例中,我们使用NotoSansCJKsc-Regular.ttf。

    以下是实现音视频对齐并添加中文字幕的完整Python代码。你可以将这段代码保存为一个Python文件,并根据需要进行调用。

    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):
        # 使用正则表达式匹配所有标点符号并替换为 @
        result = re.sub(r'[^ws]', '@', input_string)
        return result
    
    def add_chinese_subtitle_to_frame(frame, subtitle_text, position, font_path, font_size, font_color):
        # 将OpenCV图像转换为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图像转换回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):
        # 加载音频文件并调整音量
        original_audio = AudioSegment.from_file(audio_path)
        original_audio = original_audio + (audio_volume * 10 - 10)  # 调整音量
        silence = AudioSegment.silent(duration=500)  # 0.5秒的静音
        audio_with_silence = silence + original_audio + silence
        
        # 创建临时文件以保存修改后的音频
        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))
    
        # 创建临时文件以存储中间视频结果
        temp_video_path = os.path.join(tempfile.gettempdir(), "temp_video.mp4")
    
        # 创建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
            # 添加当前字幕到帧
            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将音频和调整后的视频合并
        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:Users60568Picturescreate屈原mp30000002.mp3"
        video_path = r"C:Users60568Picturescreate屈原mp43.mp4"
        subtitle_text='然而屈原的直言进谏,引来了朝中权臣的嫉恨,他成为了政治斗争的牺牲品。'
        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, # 设置字体大小
                                    font_color=(255, 255, 255), # 设置字体颜色
                                    subtitle_bottom_margin=80, # 设置字幕底部的位置
                                    audio_volume=2) # 调整音频音量,1.0为原始音量,1.5为增加50%音量
    
    

    1. add_chinese_subtitle_to_frame: 这个函数将字幕添加到给定的帧上。它使用PIL库来绘制字幕,然后将图像转换回OpenCV格式。
    2. sync_audio_video_add_subtitle: 这个函数处理音频和视频的对齐,并将字幕添加到每一帧上。最终,它将处理好的视频和音频合并,并生成输出文件。

    在此代码中,我们特别强调了保证音频长度不变,通过调整视频的帧率来匹配音频长度。这是通过计算新的帧率 new_fps 实现的:

    new_fps = fps * (video_duration / audio_duration)
    

    你可以通过调整以下参数来修改字幕的显示效果和位置:

    • font_size: 字体大小。
    • font_color: 字体颜色。
    • subtitle_bottom_margin: 字幕距离视频底部的距离。

    你可以使用提供的示例用法来运行代码,只需将audio_pathvideo_pathfont_path替换为你自己的文件路径即可。

    通过这个教程,你应该能够使用Python轻松地实现视频和音频的对齐,并在视频中添加中文字幕。

    以上就是基于Python实现视频和音频长度对齐合成并添加字幕功能的详细内容,更多关于Python视频和音频对齐并添加字幕的资料请关注风君子博客其它相关文章!

    您可能感兴趣的文章:

    • Python基于MoviePy实现一键提取视频音频并生成MP3
    • 详解如何使用Python提取视频文件中的音频
    • Python脚本实现音频和视频格式转换
    • Python实现视频转换为音频的方法详解
    • python中视频音频的剪辑与处理实现

    站内搜索