在本教程中,我们将学习如何使用Python和FFmpeg这将使我们能够把录音变成很酷的视频,可以很容易地在社交媒体上分享。
在本教程的末尾,我们将把声音录制转换成类似于以下内容的视频:
要遵循本教程,您需要以下组件:
在本节中,我们将创建我们的项目目录,在这个目录中,我们将创建子目录,在那里我们将存储将在本教程中使用的记录、图像、字体和视频。最后,我们将创建Python文件,该文件将包含允许我们使用FFmpeg创建和编辑视频的代码。
打开终端窗口并输入以下命令以创建项目目录:
mkdir twilio-turn-recording-to-video
cd twilio-turn-recording-to-video
使用以下命令创建四个子目录:
mkdir images
mkdir fonts
mkdir videos
mkdir recordings
这个images目录是我们将存储我们的视频背景图像的地方。下载这幅图像,并将其存储在images具有名称的目录bg.png。此映像最初是从Freepik.com .
在fonts目录中存储用于在视频中写入文本的字体文件。下载这种字体,并将其存储在fonts具有名称的目录LeagueGothic-CondensedRegular.otf。此字体最初是从Fontsquirrel.com .
这个videos目录将包含视频和动画,将添加到背景图像之上。下载这段视频中有Twilio标志的旋转记录,并将其存储在videos具有名称的目录spinningRecord.mp4。此视频中使用的源图像是从Flaticon.com .
这个recordings目录是我们将存储将变成视频的声音记录的地方。将您自己的一个或多个语音记录添加到此目录中。
现在我们已经创建了所需的所有目录,打开您最喜欢的代码编辑器并创建一个名为main.py在项目的顶层目录中。此文件将包含负责将我们的录音转换为视频的代码。
如果您不想遵循本教程的每一步,您可以获得完整的项目源代码这里 .
在本节中,我们将添加允许我们将录音转换为显示录音声波的视频的代码。
我们要用FFmpeg从音频文件生成视频。因此,为了从Python调用FFmpeg和相关程序,我们将使用python的subprocess模块。
在main.py档案:
import subprocess
def run_command(command):
p = subprocess.run(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
print('Done!!!')
print('stdout:\n{}'.format(p.stdout.decode()))
return p.stdout.decode().strip()
在上面的代码块中,我们导入了subprocess模块并创建了一个run_command()功能。顾名思义,这个函数负责运行在参数中传递的命令。当命令完成时,我们打印输出并将其返回给调用者。
下面添加以下代码run_command()职能:
def get_rec_duration(rec_name):
rec_path = "./recordings/{}".format(rec_name)
command = "ffprobe -i {rec_path} -show_entries format=duration -v quiet \
-of csv=\"p=0\"".format(rec_path=rec_path)
rec_duration = run_command(command)
print("rec duration", rec_duration)
return rec_duration
在这里,我们创建了一个名为get_rec_duration()。此函数负责检索记录的持续时间。函数接收一个记录名称(rec_name)作为参数,它以记录目录的名称作为前面,并存储在rec_path局部变量
这个ffprobe程序是FFmpeg的一部分,用于创建命令字符串以获取录制的持续时间。我们称之为run_command()函数,并将返回的值存储在rec_duration .
最后,打印并返回所获得的录制时间。
需要记录持续时间来指定将由其生成的视频的持续时间是相同的。
下面添加以下代码get_rec_duration()职能:
def turn_audio_to_video(rec_name, rec_duration):
rec_path = "./recordings/{}".format(rec_name)
bg_image_path = "./images/bg.png"
video_name = "video_with_sound_waves.mp4"
command = 'ffmpeg -y -i {rec_path} -loop 1 -i {bg_image_path} -t {rec_duration} \
-filter_complex "[0:a]showwaves=s=1280x150:mode=cline:colors=00e5ff[fg]; \
drawbox=x=0:y=285:w=1280:h=150:[email protected]:t=fill[bg]; \
[bg][fg]overlay=format=auto:x=(W-w)/2:y=(H-h)/2 " \
-map 0:a -c:v libx264 -preset fast -crf 18 -c:a aac \
-shortest ./videos/{video_name}'.format(
rec_path=rec_path,
bg_image_path=bg_image_path,
rec_duration=rec_duration,
video_name=video_name,
)
print(video_name)
run_command(command)
return video_name
这个turn_audio_to_video()功能将将录音转换为显示录音声波的视频。函数以记录名称(rec_name)和录制时间(rec_duration ).
从音频生成视频的ffmpeg命令使用记录路径(rec_path),指向背景图像的路径(bg_image_path),以及视频的输出文件名(video_name ).
让我们仔细看看FFmpeg命令:
ffmpeg -y -i {rec_path} -loop 1 -i {bg_image_path} -t {rec_duration} \
-filter_complex \"[0:a]showwaves=s=1280x150:mode=cline:colors=00e5ff[fg]; \
drawbox=x=0:y=285:w=1280:h=150:[email protected]:t=fill[bg]; \
[bg][fg]overlay=format=auto:x=(W-w)/2:y=(H-h)/2 \" \
-map 0:a -c:v libx264 -preset fast -crf 18 -c:a aac -shortest ./videos/{video_name}
这个-y告诉ffmpeg,如果输出文件存在于磁盘上,则重写它。
这个-i选项指定输入。在这种情况下,我们有两个输入文件,记录文件,rec_path,我们使用的图像有一个背景,存储在bg_image_path .
这个-loop选项通过重复(循环)输入文件生成视频。在这里,我们正在循环我们的图像输入bg_image_path。默认值是0(不要循环),所以我们把它设为1(循环)在所有视频帧中重复此图像。
这个-t选项指定持续时间(以秒为单位),或使用"hh:mm:ss[.xxx]"语法。这里我们使用的是录制时间(rec_duration值来设置输出视频的持续时间。
-filter_complex允许我们定义一个复杂的过滤器,一个输入和/或输出的任意数量。这是一个复杂的选项,需要一些参数,下面将讨论。
首先,我们使用showwaves过滤器以转换语音记录,引用为[0:a],到视频输出。这个s参数用于指定输出的视频大小,我们将其设置为1280x150。这个mode参数定义如何绘制音频波形。可用的值是:point , line , p2p,和cline。这个colors参数指定波形的颜色。波形图被指定为标签。[fg] .
我们使用drawbox过滤器,以绘制一个彩色框在我们的背景图像顶部,以帮助波形突出。这个x and y参数指定框的左上角坐标,而w and h设置它的宽度和高度。这个color参数将框的颜色配置为black不透明度为80%。这个t参数设置框边框的厚度。通过将值设置为fill我们创造了一个坚固的盒子。
要完成此筛选器的定义,我们使用overlay将波形绘图放在黑匣子顶部。这个overlay过滤器配置为format,它自动设置像素格式,以及x and y,指定叠加将放置在视频帧中的坐标。我们用一些数学来说明x和y应该放在我们的视频中心。
这个-map选项用于选择输入中的哪些流应包括或排除在输出中。我们选择将记录的所有流添加到输出视频中。
这个-c:v选项用于用特定的编解码器对视频流进行编码。我们告诉FFmpeg使用libx264编码器。
这个-preset选项选择一组选项,这些选项将提供一定的编码速度与压缩比。我们使用的是fast在此选项,但请随时更改预设为一个较慢(更好的质量)或更快(较低的质量),如果你愿意的话。
这个-crf选项代表恒速因子。速率控制决定每个帧将使用多少位。这将决定文件大小和输出视频的质量。推荐值18以获得视觉无损质量。
这个-c:a选项用于用特定的编解码器对音频流进行编码。我们用AAC编解码器。
这个-shortest选项告诉FFmpeg在最短的输入流结束时停止写入输出。
这个./videos/{video_name}选项指定输出文件的路径。
如果您是好奇的话,下面是上面讨论的所有FFmpeg波形模式所做的事情,以及它们的外观。
Point为每个样本绘制一个点:
Line为每个样本绘制一条垂直线:
P2p为每个样本绘制一个点,并在它们之间画一条线:
Cline为每个样本绘制一条中心垂直线。这是我们在本教程中使用的
下面添加以下代码turn_audio_to_video()职能:
def main():
rec_name = "rec_1.mp3"
rec_duration = get_rec_duration(rec_name)
turn_audio_to_video(rec_name,rec_duration)
main()
在这个新引入的代码中,我们有一个名为main()。在其中,我们将记录名存储在一个名为rec_name。您应该更新这一行,以包括您自己的语音记录文件的名称。
在那之后,我们称之为get_rec_duration()函数以获取录制时间。
然后,我们称之为turn_audio_to_video函数,并将返回的值存储在名为video_with_sound_waves .
最后,我们称之为main()函数来运行整个进程。请记住替换rec_name变量,其中包含要处理的录音的名称。
回到终端,运行以下命令生成视频:
python main.py
查找名为video_with_sound_waves.mp4在videos目录,打开它,您将看到类似于以下内容的内容:
在本节中,我们将在生成的视频的左下角添加一个旋转记录的视频。我们要添加的视频存储在名为spinningRecord.mp4在videos目录。
返回到代码编辑器,打开main.py文件,并将以下代码添加到turn_audio_to_video()职能:
def add_spinning_record(video_name, rec_duration):
video_path = "./videos/{}".format(video_name)
spinning_record_video_path = "./videos/spinningRecord.mp4"
new_video_name = "video_with_spinning_record.mp4"
command = 'ffmpeg -y -i {video_path} -stream_loop -1 -i {spinning_record_video_path} \
-t {rec_duration} -filter_complex "[1:v]scale=w=200:h=200[fg]; \
[0:v] scale=w=1280:h=720[bg], [bg][fg]overlay=x=25:y=(H-225)" \
-c:v libx264 -preset fast -crf 18 -c:a copy \
./videos/{new_video_name}'.format(
video_path=video_path,
spinning_record_video_path=spinning_record_video_path,
rec_duration=rec_duration,
new_video_name=new_video_name,
)
print(new_video_name)
run_command(command)
return new_video_name
在这里,我们创建了一个名为add_spinning_record()。此函数将负责添加spinningRecord.mp4视频顶部显示声波。它以先前生成的视频的名称作为参数(video_name)和录制时间(rec_duration ).
此函数还运行FFmpeg。下面是详细的命令:
$ ffmpeg -y -i {video_path} -stream_loop -1 -i {spinning_record_video_path} \
-t {rec_duration} -filter_complex \"[1:v]scale=w=200:h=200[fg]; \
[0:v] scale=w=1280:h=720[bg], [bg][fg]overlay=x=25:y=(H-225)\" \
-c:v libx264 -preset fast -crf 18 -c:a copy ./videos/{new_video_name}
上面的命令有以下选项:
这个-y , -t , -c:v , -preset,和-crf选项与生成音频波形的FFmpeg命令中的选项相同。
这个-i选项之前也使用过,但在本例中,我们有两个视频作为输入文件,在前一步中生成的视频文件和旋转记录视频文件。
这个-stream_loop选项允许我们设置输入流被循环的次数。值0表示禁用循环,而-1表示无限循环。我们将旋转记录视频设置为无限循环。这将使FFmpeg无限期地对输出视频进行编码,但由于我们还指定了输出视频的持续时间,FFmpeg将在视频到达此持续时间时停止编码。
这个-filter_complex选项:也具有与前面相同的功能,但是这里有两个视频作为输入文件,这是在上一节中创建的视频。[0:v]还有旋转录像[1:v] .
过滤器首先使用scale若要调整旋转记录视频的大小,使其具有200x200维,并将[fg]标签。然后,我们使用scale再次筛选,将上一节中创建的视频设置为1280x720大小,[bg]标签。最后,我们使用overlay过滤器,将旋转记录视频放在上一节中创建的视频之上,在坐标中。x=25,和y=H-225(h代表视频高度)。
这个-c:a选项也在上一节中引入,但在本例中,我们使用的是特殊值。copy若要告诉ffmpeg复制源视频中的音频流而不重新编码它,请执行以下操作。
命令的最后一部分,./videos/{new_video_name}设置输出文件的路径。
替换main()函数,它将调用添加到add_spinning_record()职能:
def main():
rec_name = "rec_1.mp3"
rec_duration = get_rec_duration(rec_name)
video_with_sound_waves = turn_audio_to_video(rec_name, rec_duration)
add_spinning_record(video_with_sound_waves, rec_duration)
在终端中运行以下命令生成视频:
python main.py
查找名为video_with_spinning_record.mp4在videos目录,打开它,您将看到类似于以下内容的内容:
在本节中,我们将在视频的顶部添加一个标题。作为其中的一部分,我们将学习如何使用FFmpeg绘制文本,更改颜色、大小、字体和位置。
返回到代码编辑器,打开main.py文件,并将以下代码添加到add_spinning_record职能:
def add_text_to_video(video_name):
video_path = "./videos/{}".format(video_name)
new_video_name = "video_with_text.mp4"
font_path = "./fonts/LeagueGothic-CondensedRegular.otf"
command = "ffmpeg -y -i {video_path} -vf \"drawtext=fontfile={font_path}: \
text='Turning your Twilio voice recordings into videos':fontcolor=black: \
fontsize=90:box=1:[email protected] \
:boxborderw=5:x=((W/2)-(tw/2)):y=100\" \
-c:a copy ./videos/{new_video_name}".format(
video_path=video_path,
font_path=font_path,
new_video_name=new_video_name
)
print(new_video_name)
run_command(command)
return new_video_name
在这个函数中,我们创建了一个名为add_text_to_video()调用一个新的Ffmpeg命令来绘制文本。让我们仔细看看FFmpeg命令:
ffmpeg -y -i {video_path} -vf \"drawtext=fontfile={font_path}: \
text='Turning your Twilio voice recordings into videos':fontcolor=black: \
fontsize=90:box=1:[email protected]:boxborderw=5:x=((W/2)-(tw/2)):y=100\" \
-c:a copy ./videos/{new_video_name}
这个-y,以及-c:a选项的使用与以前完全相同。
这个-i选项,它定义输入,现在只有一个输入文件,即上一节中生成的视频文件。
这个-vf选项允许我们创建一个简单的filtergraph用它过滤流。这里我们使用drawtext筛选器将文本绘制到视频的顶部,并包含多个参数:fontfile是用于绘制文本的字体文件,text定义要绘制的文本(根据您的喜好随意更改它),fontcolor将文本颜色设置为黑色,fontsize设置文本大小,box若要启用文本周围的框,boxcolor若要将此框的颜色设置为white有50%的不透明度,boxborderw若要设置边框的宽度,请执行以下操作x and y若要设置要打印文本的视频中的位置,请执行以下操作。我们用一点数学来画以文本为中心的文字。
这个./videos/{new_video_name}选项的末尾设置输出文件,就像前面的FFmpeg命令一样。
替换main()函数具有以下版本,该版本添加标题步骤:
def main():
rec_name = "rec_1.mp3"
rec_duration = get_rec_duration(rec_name)
video_with_sound_waves = turn_audio_to_video(rec_name, rec_duration)
video_with_spinning_record = add_spinning_record(video_with_sound_waves, rec_duration)
video_with_text = add_text_to_video(video_with_spinning_record)
返回到您的终端,并运行以下命令生成一个标题为:
python main.py
查找名为video_with_text.mp4在videos目录,打开它,您将看到类似于以下内容的内容:
在本教程中,我们学习了如何使用FFmpeg中的一些高级选项将语音记录转换为可以在社交媒体上共享的视频。我希望这能鼓励你更多地了解FFmpeg。
源码:关注:Python源码 领取整项目完整代码