利用moviepy模块将图片转换为视频

2022-05-09 20:25:08 浏览数 (1)

前言

前几天分享了如何将数据可视化,使数据动起来。最近又有对可视化有点着迷,想着让图片动起来,然后加上语音说明。然后经过搜索,通过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分钟

0 人点赞