前言
前几天分享了如何将数据可视化,使数据动起来。最近又有对可视化有点着迷,想着让图片动起来,然后加上语音说明。然后经过搜索,通过moviepy模块可以实现。折腾了两天,终于搞定。
使用Pandas_Alive做数据可视化,使图表动起来
主要函数
文字转语音
通过调用百度api接口实现
代码语言:javascript复制def text_to_mp3_by_api(text):
"""
通过网络接口将文字转换成语音
"""
time.sleep(1)
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
result = client.synthesis(text = text, options={'vol':5})
mp3_path = './data/mp3/{}.mp3'.format(text)
if not isinstance(result, dict):
with open(mp3_path, 'wb') as fw:
fw.write(result)
else:
print(result)
def pic_to_mp3():
"""
根据图片文件名生成mp3语音
"""
mp3_list = []
for f in listdir('./data/mp3/'):
mp3_list.append(path.splitext(f)[0])
for fn in listdir('./data/wx/'):
basename = path.splitext(fn)[0]
text = basename.split('_')[1]
if text not in mp3_list:
print('正在处理...[{}]'.format(text))
text_to_mp3_by_api(text)
else:
print('跳过...[{}]'.format(text))
图片生成视频
代码语言:javascript复制def pic_to_mp4(pic_dir, title, h_flag):
"""
图片转视频
"""
#图片集,语音集,视频集,字幕集
pic_files = []
mp3_clips = []
image_clips = []
txt_clips = []
#字幕开始时间
time_pos = 0
#图片列表
pic_files = [join(pic_dir,fn) for fn in listdir(pic_dir) if fn.endswith('.jpeg')]
pic_files.sort(key=lambda fn:int(findall(r'd ', fn)[-1]))
#片头
mp3_list = []
for f in listdir('./data/mp3/'):
mp3_list.append(path.splitext(f)[0])
if title not in mp3_list:
print('正在处理title...[{}]'.format(title))
text_to_mp3_by_api(title)
else:
print('跳过...[{}]'.format(title))
mp3_path = './data/mp3/{}.mp3'.format(title)
mp3_clip = AudioFileClip(mp3_path)
mp3_clips.append(mp3_clip)
txt_clip = (TextClip(title, fontsize=120,
font='./data/font/SIMSUN.TTC',
method='label',
align='center', color='red')
.set_position('center')
.set_duration(mp3_clip.duration).set_start(time_pos))
txt_clips.append(txt_clip)
time_pos = time_pos mp3_clip.duration
image_clips.append(ImageClip(pic_files[5], duration=mp3_clip.duration))
#正剧
for pic in pic_files:
txt = path.splitext(pic)[0].split('_')[1]
#音频处理
mp3_path = './data/mp3/{}.mp3'.format(txt)
mp3_clip = AudioFileClip(mp3_path)
mp3_clips.append(mp3_clip)
#字幕处理
mul = math.ceil(len(txt)/14)
per_duration = mp3_clip.duration/mul
for i in range(mul):
s_pos = i*14
e_pos = s_pos 14
if e_pos > len(txt):
e_pos = len(txt)
#print(i,s_pos,e_pos)
#print(txt[s_pos:e_pos])
txt_clip = (TextClip(txt[s_pos:e_pos], fontsize=60,
font='./data/font/SIMSUN.TTC', size=(900, 200),
align='center', color='red')
.set_position('bottom')
.set_duration(per_duration).set_start(time_pos i*per_duration))
txt_clips.append(txt_clip)
#视频处理
image_clips.append(ImageClip(pic, duration=mp3_clip.duration))
#字幕时间处理
time_pos = time_pos mp3_clip.duration
#合成视频
videocct = concatenate_videoclips(image_clips)
#语音合成
mp3cct = concatenate_audioclips(mp3_clips)
mp3cct.volumex(1.0)
#背景音乐
bgm_files = [join('./data/bgm/',fn) for fn in listdir('./data/bgm/') if fn.endswith('.mp3')]
cur = random.randrange(len(bgm_files)-1)
print(bgm_files[cur])
#音量
bgm_clip = AudioFileClip(bgm_files[cur]).volumex(0.05)
bgm_loop = afx.audio_loop(bgm_clip, duration=mp3cct.duration)
#最终语音
mp3_final = CompositeAudioClip([mp3cct, bgm_loop])
#添加字幕
videocct = CompositeVideoClip([videocct, *txt_clips])
#添加语音
videocct = videocct.set_audio(mp3_final)
#保存结果
videocct.write_videofile('./output/{}.mp4'.format(title), fps=12, audio_codec='aac')
#竖屏转换成横屏
if h_flag:
v_to_h('./output/{}.mp4'.format(title))
print('完成')
竖屏视频转横屏
通过ffmpeg工具实现
代码语言:javascript复制def v_to_h(mp4_path):
"""
竖屏转换成横屏视频
"""
cwd = getcwd()
res_path = mp4_path.split('/')[-1]
cmd="ffmpeg -i {1}/{0} -lavfi '[0:v]scale=ih*16/9:-1,boxblur=luma_radius=min(h,w)/20:luma_power=1:chroma_radius=min(cw,ch)/20:chroma_power=1[bg];[bg][0:v]overlay=(W-w)/2:(H-h)/2,crop=h=iw*9/16' -vb 800K {1}/output/h_{2}".format(mp4_path, cwd, res_path)
system(cmd)
附:横屏转竖屏参考
代码语言:javascript复制ffmpeg -i input.mp4 -lavfi "[0:v]scale=256/81*iw:256/81*ih,boxblur=luma_radius=min(h,w)/40:luma_power=3:chroma_radius=min(cw,ch)/40:chroma_power=1[bg];[bg][0:v]overlay=(W-w)/2:(H-h)/2,setsar=1,crop=w=iw*81/256" output.mp4
本文共 259 个字数,平均阅读时长 ≈ 1分钟