CCF BDCI 文心大模型创意项目】中秋款文心带你轻松搞定MV制作

本文涉及的产品
交互式建模 PAI-DSW,5000CU*H 3个月
模型训练 PAI-DLC,5000CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
简介: CCF BDCI 文心大模型创意项目】中秋款文心带你轻松搞定MV制作

项目背景

这个项目的启发,当然是来自我们无敌的磊哥


ninetailskim


看到磊哥用剪辑软件做出来的MV,我想着,我们可以用python来实现一款相对自动化的全流程MV生成工具。


在这里项目,我们只需要放入歌曲and歌曲的lrc文件以及一张首页图即可得到最终的MV

话不多说,肝着!


导入一些必备的包

# 用来剪切音频和转换mp3为wav
!pip install pydub
!pip install moviepy
!pip install auditok


文本处理

我们要拿到音频的时间点,以及文本,才能去进行一个文生图


我本来写了一个自动智能化根据静默时间切分音频的代码,结果,因为歌曲有背景曲效果很差,那就算了吧


有兴趣尝试自动切分音频并提取文本的可以参考我之前的项目:

[PaddleSpeech]助力视频字幕生成演讲稿提取


这里直接使用Lrc文件看效果,后续找到解决方案再去实现这个坑

目标:

  1. 时间节点
  2. 时间节点对应的文本


时间节点、歌词 获取

# 暂时没有找到比较合适的文本提取并且找到对应时间戳的工具
# 已有的 import auditok auditok.split这样的效果都不好
# 我暂且我找的歌曲的Lrc歌词文件
def readLrc(path = '水调歌头.lrc'):
    lines = []
    texts = []
    f = open(path,'r')
    while True:
        line = f.readline()  #包括换行符
        line = line[:-1]   #去掉换行符
        if line:
            if ('.' in line):
                timeMin = line.strip().split(']')[0][1:3]
                timeSec = line.strip().split(']')[0][4:6]
                text = line.strip().split(']')[1]
                lines.append([timeMin,timeSec])
                texts.append(text)
        else:
            break
    f.close()
    return lines,texts
info,text = readLrc('水调歌头.lrc')
print(info[0])
['00', '01']
text
['水调歌头',
 '作詞∶苏轼',
 '作曲∶梁弘志',
 '演唱∶王菲',
 '明月几时有  把酒问青天',
 '不知天上宫阙 今夕是何年',
 '我欲乘风归去 唯恐琼楼玉宇',
 '高处不胜寒 起舞弄清影 何似在人间',
 '转朱阁 低绮户 照无眠',
 '不应有恨 何事长向别时圆',
 '人有悲欢离合 月有阴晴圆缺',
 '此事古难全 但愿人长久 千里共婵娟',
 '^_^  ~~~MUSIC~~~  ^_^',
 '我欲乘风归去 唯恐琼楼玉宇',
 '高处不胜寒 起舞弄清影 何似在人间',
 '转朱阁 低绮户 照无眠',
 '不应有恨 何事长向别时圆(别时圆)',
 '人有悲欢离合 月有阴晴圆缺',
 '此事古难全 但愿人长久 千里共婵娟',
 '~END']


文心大模型

AK和SK的获取:

https://wenxin.baidu.com/moduleApi/key

当然因为这里要生成很多的图片,要等待很久!


生成图片

!pip install wenxin-api
from tqdm import tqdm
import wenxin_api
from wenxin_api.tasks.text_to_image import TextToImage
# 下面我们安装并导入ernie_vilg模块
# 因为需要发送请求,并等待数据返回,所以,会很慢,这取决于歌词条目的数量
pro= [] # 记录单片段歌词
def get_img(texts):
    # 你的prompt 我这里发现用逗号连接词语效果更佳
    # text_prompt = "程序员,写代码"
    imgs = []
    img_num = [] # 统计这一行歌词生成了几张图片的列表
    for i in tqdm(range(len(texts))):
        t = texts[i].replace(' ',',').split(',')
        img_num.append(len(t))
        for j in t:
            pro.append(j)
            text_prompt = j + ',圆月亮,夜晚,古风'
            wenxin_api.ak = "RgCyG5U1o9CsRr2T9exS4F47TZCgswnV"
            wenxin_api.sk = "PobN54TGDMwuFY0iens5bqsQWQxq8F44"
            input_dict = {
                "text": text_prompt,
                "style": "油画"
            }
            rst = TextToImage.create(**input_dict)
            imgs.append(rst['imgUrls'][0])
    return imgs,img_num
img_list,img_num = get_img(text)


下载图片

import requests
import os
from PIL import Image
import matplotlib.pyplot as plt
%matplotlib inline
# 生成存图的目录
def init_mkdir(data_path):
    if not os.path.exists(data_path): # 判断文件夹是否存在
        os.makedirs(data_path) # 不存在则新建文件夹
init_mkdir('output-img')
# 展示生成的图片并保存
for i in range(len(img_list)):
    #使用requests直接get 下载图片使用
    r = requests.get(img_list[i])
    ii = '%02d'%i +'.png'
    out_ii = 'output-img/' + ii
    with open(out_ii, 'wb') as f:
        f.write(r.content)
    f.close()
    img_ = Image.open(out_ii)
    plt.show()
    plt.imshow(img_) 


import os
import cv2
file_dir = 'output-img'
# 返回path下所有文件构成的一个list列表
filelist = os.listdir(file_dir)
# 保证读取按照文件的顺序
filelist.sort()
if ('.ipynb_checkpoints' in filelist):
    del filelist[0]
print(filelist)
['00.png', '01.png', '02.png', '03.png', '04.png', '05.png', '06.png', '07.png', '08.png', '09.png', '10.png', '11.png', '12.png', '13.png', '14.png', '15.png', '16.png', '17.png', '18.png', '19.png', '20.png', '21.png', '22.png', '23.png', '24.png', '25.png', '26.png', '27.png', '28.png', '29.png', '30.png', '31.png', '32.png', '33.png', '34.png', '35.png', '36.png', '37.png', '38.png', '39.png', '40.png', '41.png', '42.png', '43.png', '44.png']


图片加歌词

给图片加歌词

每一张图片的歌词如下:

前面以及存储过了

pro变量中

from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
font = ImageFont.truetype("simhei.ttf",58)#设置字体和字体大小
font1 = ImageFont.truetype("STHUPO.TTF",36)#设置字体和字体大小
font2 = ImageFont.truetype("STXINGKA.TTF",55)#设置字体和字体大小
changed = 'output-text-img'
init_mkdir(changed)
def addTexttoImg():
    for i in range(len(pro)):
        imageFile = file_dir + '/' + filelist[i]
        tp=Image.open(imageFile)
        # 在图片上添加文字
        draw = ImageDraw.Draw(tp)
        draw.text((50, 50),'本歌曲由文心大模型生成图片',(255, 153, 0),font=font1) #分别设置文字的xy坐标,文字内容,文字颜色,字体
        draw.text((100, 850),pro[i],(0, 153, 255),font=font2) #分别设置文字的xy坐标,文字内容,文字颜色,字体
        draw.text((102, 852),pro[i],(255,255,255),font=font2) #分别设置文字的xy坐标,文字内容,文字颜色,字体
        draw = ImageDraw.Draw(tp)
        # 保存
        tp.save(changed + '/' + filelist[i]) #图片保存路径
addTexttoImg()


视频生成

这里是真的花了我好多的时间去设计如何让时间节点把所有的歌词对应的比较完美一些

处理时间节点

这个时间决定了我们需要插入多少张图片

PS 先知: 这里我们可以设置视频的帧数为5,后续视频生成也会用的到

因为我们图片不多

其次,要计算好时间需要多少张图片

如下:

# 总共262秒左右
4*60+22
262
# 我们最终需要1310张的图片才行
5*262
1310


生成策略

合成视频

我这里采取的策略是一秒的五帧都是相同的图片

然后我们上面有提取的时间节点,卡点加入后面的图片

# 时间序列
info
[['00', '01'],
 ['00', '04'],
 ['00', '06'],
 ['00', '08'],
 ['00', '11'],
 ['00', '22'],
 ['00', '32'],
 ['00', '44'],
 ['01', '03'],
 ['01', '14'],
 ['01', '27'],
 ['01', '38'],
 ['01', '56'],
 ['02', '27'],
 ['02', '38'],
 ['02', '57'],
 ['03', '08'],
 ['03', '30'],
 ['03', '41'],
 ['04', '15']]
# 求出每个时间段需要多少张图片
time_img = []
start = 0
for i in info:
    # 时间差
    end = int(i[0])*60 +int(i[1])
    time_img.append((end-start)*5)
    start = end
time_img.append(7*5) # 最后一段不要忘记了
sum(time_img)
1310
# 第一段时间留给首页 一秒 删除第一段,我们自行加首页,我已经放在了左侧的目录中
del time_img[0]


综上

我们的处理逻辑如下:

375e0b5a74094b7fbc57f544085b155e.png

此外:我采取时间段内的图片均分填充


视频所需要的图片列表

import os
import cv2
#造新的图片列表 1310 + 5(首页面) 张的
new_list = []
for i in range(5):
    new_list.append("home.png")
num = 0
#  0-20          
for j in range(len(time_img)): # 总共有多少个时间段 len(time_img) = 21 同时,前面还记录了每个时间段有多少张图片,就是 img_num
    #  0-5             5
    #  0-15           15
    for n in range(time_img[j]): # 每个时间段需要多少张图片
        if (img_num[j] == 1):
            new_list.append(changed + '/' + filelist[sum(img_num[:j])])
        if (img_num[j] == 2):
            if (n < (time_img[j]//2)):
                new_list.append(changed + '/' + filelist[sum(img_num[:j])])
            else:
                new_list.append(changed + '/' + filelist[sum(img_num[:j])+1])
        if (img_num[j] == 3):
            if (n < (time_img[j]//3)):
                new_list.append(changed + '/' + filelist[sum(img_num[:j])])
            elif (n < (time_img[j]//3)*2):
                new_list.append(changed + '/' + filelist[sum(img_num[:j])+1])
            else:
                new_list.append(changed + '/' + filelist[sum(img_num[:j])+2])
        if (img_num[j] == 5):
            if (n < (time_img[j]//5)):
                new_list.append(changed + '/' + filelist[sum(img_num[:j])])
            elif (n < (time_img[j]//5)*2):
                new_list.append(changed + '/' + filelist[sum(img_num[:j])+1])
            elif (n < (time_img[j]//5)*3):
                new_list.append(changed + '/' + filelist[sum(img_num[:j])+2])
            elif (n < (time_img[j]//5)*4):
                new_list.append(changed + '/' + filelist[sum(img_num[:j])+3])
            else:
                new_list.append(changed + '/' + filelist[sum(img_num[:j])+4])
new_list


len(new_list)
1310


图片列表转视频

import cv2
# VideoWriter是cv2库提供的视频保存方法,将合成的视频保存到该路径中
# 'MJPG'意思是支持jpg格式图片
# fps = 5代表视频的帧频为5,如果图片不多,帧频最好设置的小一点
# (1280,720)是生成的视频像素1280*720,一般要与所使用的图片像素大小一致,否则生成的视频无法播放
# 定义保存视频目录名称和压缩格式,像素为1280*720
video = cv2.VideoWriter('test.mp4',cv2.VideoWriter_fourcc(*'mp4v'),5,(1080,980))
for i in range(len(new_list)):
    #读取图片
    img = cv2.imread(new_list[i]) 
    # resize方法是cv2库提供的更改像素大小的方法
    # 将图片转换为1024*720像素大小
    img = cv2.resize(img,(1080,980))
    # 写入视频
    video.write(img)
# 释放资源
video.release()


音视频合并

from moviepy import *
from moviepy.editor import *
# pip install moviepy
def merge():
    video_path = 'test.mp4'
    audio_path = 'sdgt_wf.mp3'
    # 提取音轨
    audio = AudioFileClip(audio_path)
    # 读入视频
    video = VideoFileClip(video_path)
    # 将音轨合并到视频中
    video = video.set_audio(audio)
    # 输出
    video.write_videofile(f"output.mp4")
if __name__ == '__main__':
deo = video.set_audio(audio)
    # 输出
    video.write_videofile(f"output.mp4")
if __name__ == '__main__':
    merge()


项目总结

整个 项目的流程完成还是非常的费事

  1. 文本的提取
  2. 图片的生成
  3. 文本合并
  4. 图片列表生成
  5. 视频合成
  6. 音频合成

目前的视频生成还没有做到全自动,并且细节是不够完善的

相关文章
|
6月前
|
存储 SQL 人工智能
新年将至,为大家推荐一款开源AI红包封面制作神器AiCover!
新年将至,为大家推荐一款开源AI红包封面制作神器AiCover!
103 2
|
6月前
|
机器学习/深度学习 人工智能 搜索推荐
小红书开源「InstantID」,2024第一个爆火的Al写真项目,惊艳了!
小红书开源「InstantID」,2024第一个爆火的Al写真项目,惊艳了!
264 0
|
3月前
|
数据采集 机器学习/深度学习 人工智能
Datawhale AI夏令营第四期魔搭-AIGC文生图方向Task1笔记
这段内容介绍了一个使用Stable Diffusion与LoRA技术创建定制化二次元图像生成模型的全流程。首先,通过安装必要的软件包如Data-Juicer和DiffSynth-Studio准备开发环境。接着,下载并处理二次元图像数据集,利用Data-Juicer进行数据清洗和筛选,确保图像质量和尺寸的一致性。随后,训练一个针对二次元风格优化的LoRA模型,并调整参数以控制模型复杂度。完成训练后,加载模型并通过精心设计的提示词(prompt)生成一系列高质量的二次元图像,展示模型对细节和艺术风格的理解与再现能力。整个过程展示了从数据准备到模型训练及结果生成的完整步骤,为定制化图像提供了方向。
|
5月前
|
算法 数据挖掘 数据处理
第三届 Data-Juicer 数据挑战赛:ModelScope-Sora“数据导演”创意竞速
欢迎进入第三届 Data-Juicer 数据挑战赛:“ModelScope-Sora 文生视频大模型数据挑战赛”。
|
6月前
|
人工智能 编解码 Java
用户投稿:这款 AI 编码工具 CodeFuse 很惊艳
在 AI 时代,总是会迅速出现很多惊艳的产品工具,这些效率工具,在很大程度上推动了科技的进步。特别是在编程领域,各类工具更是层出不穷,从 GitHub Copilot 到 CodeGeeX,再到通义灵码,有很多工具在不断涌现。今天,我想和大家分享一款我最近发现的、非常出色的编程辅助工具 —— CodeFuse。
314 0
用户投稿:这款 AI 编码工具 CodeFuse 很惊艳
|
6月前
|
人工智能 IDE 开发工具
生成古风少女图片【InsCode Stable Diffusion美图活动一期】
生成古风少女图片【InsCode Stable Diffusion美图活动一期】
111 0
|
人工智能 IDE 物联网
【古风女孩-InsCode Stable Diffusion 美图活动一期】
【古风女孩-InsCode Stable Diffusion 美图活动一期】
111 1
|
人工智能 算法 Ubuntu
【朱颜不曾改,芳菲万户香。AIGC人物图片创作---InsCode Stable Diffusion 美图活动一期】
【朱颜不曾改,芳菲万户香。AIGC人物图片创作---InsCode Stable Diffusion 美图活动一期】
675 2
|
人工智能 IDE 开发工具
二次元美少女【InsCode Stable Diffusion 美图活动一期】
InsCode是一个集成了在线IDE、在线AI编程、在线算力租赁、在线项目部署以及在线SD 模型使用的综合代码开发平台。不论你是初级软件工程师,还是AI大模型爱好者,InsCode都能帮助你快速编写代码,运行项目。甚至在这里你还可以一键购买算力,训练大模型,开发自己的AI应用程序。
269 0
二次元美少女【InsCode Stable Diffusion 美图活动一期】
|
人工智能 算法 计算机视觉
击败Stable Diffusion XL,商汤绘画大模型出手即大作,论文公开、免费试玩
击败Stable Diffusion XL,商汤绘画大模型出手即大作,论文公开、免费试玩
120 0