当前位置: 首页 > news >正文

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

在许多视频编辑任务中,我们常常需要将视频和音频进行对齐,并添加字幕。本文将详细介绍如何使用Python实现这一功能,并在视频中添加中文字幕。我们将使用OpenCV处理视频帧,使用MoviePy处理音频和视频的合成,使用PIL库绘制中文字幕。

环境设置

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

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'[^\w\s]', '@', input_string)return resultdef 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 // 2y = 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 framedef 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 = 0for 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 += 1out.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 secondsfinal_clip = final_clip.subclip(0, final_clip.duration - 0.3)# Write the final video filefinal_clip.write_videofile(output_path, codec="libx264", audio_codec="aac")# Close the clips to release the filefinal_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='然而屈原的直言进谏,引来了朝中权臣的嫉恨,他成为了政治斗争的牺牲品。'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实现视频和音频长度对齐合成并添加字幕

在许多视频编辑任务中&#xff0c;我们常常需要将视频和音频进行对齐&#xff0c;并添加字幕。本文将详细介绍如何使用Python实现这一功能&#xff0c;并在视频中添加中文字幕。我们将使用OpenCV处理视频帧&#xff0c;使用MoviePy处理音频和视频的合成&#xff0c;使用PIL库绘…...

爬虫-模拟登陆博客

import requests from bs4 import BeautifulSoupheaders {user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36 } # 登录参数 login_data {log: codetime,pwd: shanbay520,wp-submit: …...

【深度学习】【NLP】Bert理论,代码

论文 &#xff1a; https://arxiv.org/abs/1810.04805 文章目录 一、Bert理论BERT 模型公式1. 输入表示 (Input Representation)2. 自注意力机制 (Self-Attention Mechanism)3. Transformer 层 (Transformer Layer) 二、便于理解Bert的代码1. 自注意力机制2. Transformer 层3. …...

element table 点击某一行中按钮加载

在Element UI中&#xff0c;实现表格&#xff08;element-table&#xff09;中的这种功能通常涉及到数据处理和状态管理。当你点击某一行的按钮时&#xff0c;其他行的按钮需要动态地切换为加载状态&#xff0c;这可以通过以下步骤实现&#xff1a; 1.表格组件&#xff1a;使用…...

Linux开机自启/etc/init.d和/etc/rc.d/rc.local

文章目录 /etc/init.d和/etc/rc.d/rc.local的区别/etc/init.dsystemd介绍 /etc/init.d和/etc/rc.d/rc.local的区别 目的不同&#xff1a; /etc/rc.d/rc.local&#xff1a;用于在系统启动后执行用户自定义命令&#xff0c;适合简单的启动任务。 /etc/init.d&#xff1a;用于管理…...

DP:两个数组的dp问题

解决两个数组的dp问题的常用状态表示&#xff1a; 1、选取第一个字符串[0-i]区间以及第二个字符串[0,j]区间作为研究对象 2、根据题目的要求确定状态表示 字符串dp的常见技巧 1、空串是有研究意义的&#xff0c;引入空串可以帮助我们思考虚拟的边界如何进行初始化。 2、如…...

嵌入式Linux:格式化I/O

目录 1、格式化输出函数 1.1、printf()函数 1.2、fprintf()函数 1.3、dprintf()函数 1.4、sprintf()函数 1.5、snprintf()函数 2、格式化输入函数 2.1、scanf()函数 2.2、fscanf()函数 2.3、sscanf()函数 在Linux中&#xff0c;格式化I/O&#xff08;formatted I/O&a…...

【elementui源码解析】如何实现自动渲染md文档-第二篇

目录 1.概要 2.引用文件 1&#xff09;components.json 2&#xff09;json-template/string 3&#xff09;os.EOL 3.变量定义 4.模版填充 5.MAIN_TEMPLATE填充 6.src下的index.js文件 1&#xff09;install 2&#xff09;export 7.总结 1.概要 今天看第二个命令no…...

热门开源项目OpenHarmony

目录 1.概述 1.1.开源项目的意义 1.2.开源项目对软件行业的促进作用 1.3.小结 2.OpenHarmony 2.1.技术架构 2.2.分布式软总线 2.2.1.架构 2.2.2.代码介绍 2.2.2.1.代码目录 2.2.2.2.说明 2.2.2.3.发现组网和传输 2.2.2.3.1.发现 2.2.2.3.2.组网 2.2.2.3.3.传输…...

NewspaceAi之GPT使用新体验

GPT功能 使用地址&#xff1a;https://newspace.ai0.cn/ 上车 挂挡 踩油门&#xff0c;一脚到底&#xff0c;开始你的表演 问题1&#xff1a;你能做什么详细告诉我&#xff1f; 下面内容是GPT的回答 当然&#xff01;作为一个基于GPT-4架构的AI&#xff0c;我能够在许多方面为…...

详解红黑树

红黑树规则 节点是红色或黑色。根节点是黑色。每个叶子节点都是黑色的空节点&#xff08;NIL节点&#xff09;。每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。 红黑树…...

探索JavaScript逆向工程与风控等级

探索JavaScript逆向工程与风控等级 在当今的网络安全领域&#xff0c;JavaScript逆向工程&#xff08;简称JS逆向&#xff09;已成为许多开发者和安全专家关注的焦点。JS逆向主要涉及对JavaScript代码的分析与理解&#xff0c;以发现其内部逻辑、数据流及潜在漏洞。这种技术常用…...

C++ 22 之 立方体案例

c22立方体案例.cpp #include <iostream> #include <string>using namespace std;class Cube{ private:int cube_l; // 长int cube_w; // 宽int cube_h; // 高public:// 设置长void set_l(int l){cube_l 1;}// 设置宽void set_w(int w){cube_w w;}// 设置高void …...

vue2使用antv/g6-editor实现可拖拽流程图

依赖下载 照着这个引入就好&#xff0c;然后npm install 源码 <template><div id"vue-g6-editor"><el-row><el-col :span"24"></el-col></el-row><!-- 工具栏 --><el-row><el-col :span"24&qu…...

springboot学习小结

背景 业务上需要开发&#xff0c;组里一位前辈给我指路 spring基础 什么是spring spring提供一个容器称为spring应用上下文&#xff0c;容器里可以创建和管理组件&#xff0c;组件会在容器里装配好&#xff0c;组件也可以叫bean。 装配不由组件创建他依赖的组件&#xff0…...

vue聊天发送Emoji表情

在用web端写聊天发送表情的功能中&#xff0c;使用web端有系统自带的unicode表情会出现每端不统一的情况&#xff0c;不好用不能统一&#xff0c;在这里我想到了一个非常好的思路&#xff0c;可以解决这个问题&#xff01; 那就是发送表情用图片的形式呈现&#xff0c;然后发给…...

360数字安全:2024年4月勒索软件流行态势分析报告

勒索软件传播至今&#xff0c;360 反勒索服务已累计接收到数万勒索软件感染求助。随着新型勒索软件的快速蔓延&#xff0c;企业数据泄露风险不断上升&#xff0c;勒索金额在数百万到近亿美元的勒索案件不断出现。勒索软件给企业和个人带来的影响范围越来越广&#xff0c;危害性…...

【MySQL】日志详解

本文使用的MySQL版本是8 日志概览 它们记录了数据库系统中的不同操作和事件&#xff0c;以便于故障排除、性能优化和数据恢复。本文将介绍MySQL中常见的几种日志&#xff0c;同时也会介绍一点常用的选项。 官方文档&#xff1a;MySQL :: MySQL 8.0 Reference Manual :: 7.4 M…...

MyBatis 延迟加载,一级缓存,二级缓存设置

MyBatis不仅提供了一级缓存和二级缓存机制&#xff0c;还支持延迟加载&#xff08;Lazy Loading&#xff09;&#xff0c;以进一步优化性能。 1. 延迟加载&#xff08;Lazy Loading&#xff09; 延迟加载是在需要时才加载数据&#xff0c;而不是在查询时立即加载所有相关数据。…...

Linux 基本指令2

cp 指令 cp[选项]源文件 目标文件 将源文件的内容复制到目标文件中&#xff0c;源文件可以有多个&#xff0c;最后一个文件为目标文件&#xff0c;目标文件也可以是一段路径&#xff0c;若目的地不是一个目录的话会拷贝失败。若没有路径上的目录则会新建一个&#xff0c;若源是…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...