营销号视频生成器(Python)

摘要:
剪辑视频→ getVideo()将行写入文本→ getText(file)获取视频总时长→ getLength(video)向视频添加背景音乐→ add_Audio(video,output='out.mp4')为视频添加字幕→ subTitle(text_file,output='out_sub.mp4')文本到语音→ 讯飞API为视频添加语音→ add_ people(mp3_file,

网上最近很火的段子是各种营销号的文案,比方说下面的段子

核桃核不能吞下去是怎么回事呢?核桃核相信大家都很熟悉,但是核桃核不能吞下去是怎么回事呢,下面就让小编带大家一起了解吧。核桃核不能吞下去,其实就是核桃核太大了,吞下去容易噎着,大家可能会很惊讶核桃核怎么会不能吞下去呢?但事实就是这样,小编也感到非常惊讶。这就是关于核桃核不能吞下去的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!

其实我平时见到这些文案或者视频都很少,因为我没用过今日头条、抖音之类的APP

然后我就在想,如果指定文案、BGM、视频,给定这三个东西,能否批量生成营销号视频,于是就有了这个项目

项目说明我录了个视频放在B站了,源码放在了Github

下面详细说明一下代码吧

设计思路
首先我把这个程序分为了以下几步:

剪裁视频→getVideo()
将台词写入文本→getText(file)
获取视频总时长→getLength(video)
给视频添加背景音乐→add_audio(video, mp3, output='out.mp4')
给视频添加字幕→subTitle(text_file, video_file, output='out_sub.mp4')
文本转人声→讯飞API
给视频添加人声→add_people(mp3_file, video_file)
清除中间生成的文件→clean()
1. 裁剪视频
对于大部分营销号视频来说,长度都在45秒左右,我也没有弄的太复杂,就直接将给定的mp4文件的前50秒保留了下来,其余的部分不要

def getVideo():
cmd = 'ffmpeg -y -i in.mp4 -ss 00:00:00 -t 00:00:50 -acodec copy -vcodec copy -async 1 in_sub.mp4'
subprocess.call(cmd, shell=True)


上面代码的意思是在cmd命令行中执行cmd这句命令,这个命令的意思是将in.mp4从0秒开始,裁剪到50秒,并保存为in_sub.mp4文件

2. 将文本写入台词
这个其实是最简单的,网上有很多“营销号文案生成器”,我随便找了个源码借鉴了下。首先你需要在一个文本文件中设定好主体、事件、另一种说法,例如

那么他就会生成文案

核桃核不能吞下去是怎么回事呢?核桃核相信大家都很熟悉,但是核桃核不能吞下去是怎么回事呢,下面就让小编带大家一起了解吧。核桃核不能吞下去,其实就是核桃核太大了,吞下去容易噎着,大家可能会很惊讶核桃核怎么会不能吞下去呢?但事实就是这样,小编也感到非常惊讶。这就是关于核桃核不能吞下去的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!

其实非常简单,就是一个字符串替换

def getText(file): # 组装台词
    with open(file) as f:
        body = f.readline().strip()
        thing = f.readline().strip()
        other_word = f.readline().strip()
    
    # 主题框架
    txt = '''{}{}是怎么回事呢?:4:0
{}相信大家都很熟悉,但是{}{}是怎么回事呢?:7:4
下面就让小编带大家一起了解吧:3:11
{}{},其实就是{}:8:15
大家可能会很惊讶{}怎么会{}呢?:6:23
但事实就是这样,小编也感到非常惊讶:5:29
这就是关于{}{}的事情了,大家有什么想法呢?:6:34
欢迎在评论区告诉小编一起讨论哦!:5:40'''.format(body, thing, body, body, thing, body, thing, other_word, body, thing, body, thing)

    # 台词写入
    with open('text.txt', mode='w') as f:
        f.write(txt)

文本后面的数字代表意思分别是字幕的持续时间、开始出现的时间。比方说下面就让小编带大家一起了解吧这句话就会从第11秒开始出现,持续显示3秒

3. 获取视频总时长
做这一步主要是考虑到BGM和视频应该差不多时长,假如BGM有60秒,视频只有50秒,那就会出现这样一个现象,整个视频的时长是60秒,但是当视频播放到第50秒之后,画面就不变化了,而BGM还在播放

所以这里获取的视频时长,是为了后面剪裁BGM使用的

但是又有人可能会觉得,你一开始不是设定了50秒,那这里为啥还要动态获取时长,而不写50秒呢?因为我考虑到后面的可扩展性,如果有用户想要修改视频时长,比方说改为60秒,那代码就有很多地方也要修改。但是如果我用一个变量来代替,用户就只需要修改第一步里的视频时长即可
————————————————

def getLength(video): # 获取视频时长
    cmd = 'ffprobe -v quiet -select_streams v -show_entries stream=duration -of csv="p=0" {video}'.format(video=video)
    seconds = os.popen(cmd, 'r')
    seconds = math.ceil(float(seconds.read()))
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    return "%02d:%02d:%02d" % (h, m, s)

由于ffmpeg这个库对时间的格式有要求,必须是00:00:00这种格式,所以我稍微做了一些处理

4. 给视频添加背景音乐
这一步里面又分三小步

裁剪BGM
降低BGM音量
给视频添加BGM
为什么要降低BGM音量,是因为我在后续测试的过程中发现BGM声音有点太大了,掩盖住了人声
————————————————

def add_audio(video, mp3, output='out.mp4'): # 将背景音乐添加到视频中
    BGM = 'ffmpeg -i {mp3} -ss 00:00:00.0 -t {time} -acodec copy BGM.mp3'.format(mp3=mp3, time=total_time)
    subprocess.call(BGM, shell=True)

    volume = 'ffmpeg -i BGM.mp3 -vcodec copy -af "volume=-20dB" BGM_volume.mp3'
    subprocess.call(volume, shell=True)
    
    command = "ffmpeg -i {mp3} -i {video} -y {output}".format(video=video, mp3='BGM_volume.mp3', output=output)
    subprocess.call(command, shell=True)

给视频添加字幕

添加字幕我用的是moviepy这个库,它里面有一个TextClip方法,参数有很多,可以非常方便的添加字幕对象,然后将这些对象和视频对象一起进行整合,就可以了

def subTitle(text_file, video_file, output='out_sub.mp4'):
    video1 = VideoFileClip(video_file)
    sentences = [] # 台词列表
    with open(text_file) as f:
        text_tmp = f.readlines()
        for i in text_tmp:
            sentences.append(i.strip().split(':'))
    print(sentences)
    
    txts = [] # 所有字幕剪辑
    with open('args.txt') as f:
        color = f.readlines()[4].strip()
        for sentence, span, start in sentences:
            txt = (TextClip(sentence, fontsize=50, align='center', color=color, font='SimHei')
                    .set_position(("center","bottom")).set_duration(int(span)).set_start(int(start)))
            txts.append(txt)

    video2 = CompositeVideoClip([video1, *txts])
    video2.write_videofile(output)
6. 文本转人声
所有的步骤都可以自己完成,唯独文本转人声不行,只能调用第三方接口,百度、腾讯、讯飞都可以,这里我用的讯飞的接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2LYUgs3u-1587353056943)(https://s1.ax1x.com/2020/04/20/JQAm8J.png#shadow)]

代码也是使用的讯飞提供的demo(python3),由于太多了,就不在这放出来了

实现的时候有一个细节要提一下,就是如何做到字幕和人声同步

从上面的添加字幕可以看出,字幕的各种时间都是设定死的,那么能操作的也就是有人声了。具体操作我是这样做的,每一个字幕,生成一个人声,一共有8段字幕,所以我有8个mp3文件,由于人声是无法设置持续时间的,只能设置什么时间开始发声,即只能设置开始时间,所以我把每一个mp3文件的开始时间都设置成每个字幕的开始时间相同。这样做就会出现一个现象,假设某一段文本非常短,很快就读完了,字幕也消失了,但是下一段字幕以及对应的人声不会立即出现,而是单纯的只有BGM,只有等这段字幕和人声到点了,它们才会出现。不过我测试了实际效果并不突兀

7. 给视频添加人声

 
def addPeople(mp3_file, video_file):
    my_clip = VideoFileClip(video_file)
    audio_background = AudioFileClip(mp3_file)
    final_audio = CompositeAudioClip([my_clip.audio, audio_background])
    final_clip = my_clip.set_audio(final_audio)
    final_clip.write_videofile('final.mp4')

8. 清除中间生成的文件

这步也非常简单,因为使用ffmpeg库的时候,中间有一些临时保存的mp3、mp4文件,在最后的时候删除掉就行了

def addPeople(mp3_file, video_file):
    my_clip = VideoFileClip(video_file)
    audio_background = AudioFileClip(mp3_file)
    final_audio = CompositeAudioClip([my_clip.audio, audio_background])
    final_clip = my_clip.set_audio(final_audio)
    final_clip.write_videofile('final.mp4')


————————————————
版权声明:本文为CSDN博主「数学家是我理想」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37236745/article/details/105619051

免责声明:文章转载自《营销号视频生成器(Python)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ubuntu 安装 wireshark各大巨头电商提供的IP库API接口新浪、搜狐、阿里下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

vue使用videojs控制后台m3u8数据请求

关于Video.js的使用方法就不再说了,有兴趣的请迁跃:https://videojs.com/ VideoJS中并没有stop之类控制后台数据请求的参数,只有暂停 video.pause()方法 ,但是对于后台的请求是不会暂停的,如果我页面有多个Vedio实例需要存在,这样就太影响页面效率了 我使用的是Vue 组件化的VedioJS控件 1、动态控...

Java 读取ANSI文件中文乱码问题解决方式[转]

第一步:首先判断源文件的编码格式: 按照给定的字符集存储文件时,在文件的最开头的三个字节中就有可能存储着编码信息,所以,基本的原理就是只要读出文件前三个字节,判定这些字节的值,就可以得知其编码的格式。其实,如果项目运行的平台就是中文操作系统,如果这些文本文件在项目内产生,即开发人员可以控制文本的编码格式,只要判定两种常见的编码就可以了:GBK和UTF-8。...

【video】使用FFmpeg将avi / mp4文件转换成m3u8/ts文件(用于近时播放)

准备工作 下载 :ffmpeg-N-102534-gec20b81302-win64-lgpl-shared.zip,并解压,FFmpeg下载地址   配置环境变量:在path中配置bin目录 (例如:F:xxxxxxffmpeg-20180227-fa0c9d6-win64-staticin)检查是否配置成功:ffmpeg -version 开始转...

Winforms开发技巧大揭秘,DevExpress查找编辑器自动搜索模式

下载DevExpress v19.2完整版  DevExpress Winforms Controls 内置140多个UI控件和库,完美构建流畅、美观且易于使用的应用程序。在前面的教程文章中,技术团队宣传了针对DevExpress LookUpEdit和GridLookUpEdit控件新的AutoSuggest模式。 简而言之,AutoSuggest允许编...

华为海思系列芯片开发学习中常见缩写详解

1. 系统控制Hi —— HiSilicon 海思半导体公司 MPP —— Media Process Platform 媒体处理平台 MPI —— MPP Programe Interface MPP程序接口 DDR —— Double Data-Rate 双倍速率,DDR SDRAM=双倍速率同步动态随机存储器,人们习惯称为DDR,其中,SDRAM 是...

kurento用gstreamer推流 RTP to RTMP

基于Gstreamer的rtp转rtmp代码 flv不支持 音频 48000. 支持44k。flv不支持音频opus格式。   1,用ffmpeg推流到rtp。 srs的示例flv文件: ffmpeg -re -stream_loop -1 -i ./doc/source.200kbps.768x320.flv -an -vcodec h264 -...