aibb / app.py
zdxpan's picture
Update app.py
933d1b0
raw
history blame
20.8 kB
import time
import random
import os
import gradio as gr
import pandas as pd
import textwrap
import traceback
# 爬虫-------------
# from save_cookie import save_cookie, get_cookie, cookie_f
# from scrap_util import getDriver, titleLocInfo, find_key_paragrap, extract_from_driver, table_record_doc
import helium as hm
# from postDouyin import senDouyin
# 模型-------------
from transformers import *
import pandas as pd
import os
import random
# import IPython.display as ipd
import numpy as np
# 视频-------------
import moviepy.video.io.ImageSequenceClip
from moviepy.editor import AudioFileClip,TextClip,CompositeVideoClip
import inspect, math
from PIL import Image, ImageDraw, ImageFont
from txtImgPost import myPost, reshape_texts, generatePost
# 发布-------------
VIPtitle = "👑潜龙在渊输入内容生成视频✍️👒"
print(f">>>{VIPtitle}")
# print(f"秘钥文件路径:{cookie_f}")
mv_path = "./movie_output"
img_path = "./imgpost"
font_path = "./fonts"
# movies = [os.path.join(mv_path,i) for i in os.listdir(mv_path) if i.endswith("mp4")]
# exam_video = movies[0]
# imgs_cur = [os.path.join(img_path,i) for i in os.listdir(mv_path) if i.endswith("png")]
templates_path = "./templates/"
templates = [os.path.join(templates_path,i) for i in os.listdir(templates_path) if i.endswith("csv")]
templates_name = [i.strip(templates_path).strip(".csv") for i in templates]
preview_templates = [os.path.join(templates_path,i) for i in os.listdir(templates_path) if i.endswith("jpg")]
# 字体------
font_list = [os.path.join(font_path,i) for i in os.listdir(font_path) if i.split(".")[1] in ["ttc", "ttf", "otf"]]
background_img = "kaobianBottem.jpeg"
background_img = "./templates/zf_board_temp.jpeg"
a_ = Image.open(background_img)
WIDTH = 900
HEIGHT = 1400
WIDTH,HEIGHT = a_.size
# should load from files and build new from file
# cookie_fns = ["抖音北京人事考试","抖音广东人事考试","抖音四川人事考试","抖音浙江人事考试","抖音江苏人事考试","抖音山东人事考试","抖音河南人事考试"]
# cookie_fns = os.listdir("./cookie_list/")
# cookie_fn = cookie_fns[0]
description = "URL--> 爬取-->解析--> 音频--> 图片--> 视频"
# driver = getDriver()
# sub_url ="https://www.js.msa.gov.cn/art/2023/2/24/art_11436_1391666.html"
# hm.set_driver(driver) # 给它一个selnuim driver
# hm.go_to(sub_url)
# html = driver.page_source
html = "<None>"
examples = [
["朝天区2023年上半年面向社会公开考试招聘事业单位工作人员公告-“四川•朝天”门户网",
"报名时间。本次公开考试招聘采取网络报名方式进行,不组织现场报名。报名时间:2023年3月10日至3月17日24:00。报名网站:广元人事考试网(http://gypta.e21cn.com/)",
"缴费时间。2023年05月27日 在 网上缴费",
"考试时间-笔试时间 2.笔试分别于2023年4月8日、9日举行(具体时间、地点见《准考证》)。\
其中,4月8日笔试科目为《教育公共基础》,4月9日笔试科目为《卫生专业技术岗位人员公共科目笔试》、《综合知识》",
"准考证领取。网上报名且缴费成功的报考者,凭身份证号、姓名,于2023年4月3日至4月7日24:00前登录报名网站打印准考证"
],
]
# 预测函数
# qa = pipeline("question-answering", model="uer/roberta-base-chinese-extractive-qa")
def custom_predict(context, question):
answer_result = qa(context=context, question=question)
answer = question + ": " + answer_result["answer"]
score = answer_result["score"]
return answer, score
def image_preview(orimage=None, text="Hello Ai", x=10, y=20, w=500, h=100, bac_color = "#FFbbFF",
txt_color = "#000000",front="simsun.ttc", size = 50):
if orimage is None:
return None
size = int(size)
image = Image.fromarray(orimage)
draw = ImageDraw.Draw(image)
draw.rectangle((x, y, x + w, y + h), fill=bac_color)
# Add text to the text box
font = ImageFont.truetype(front, size)
text_x = x + size
text_y = y + size
words_perline = int(w / size)
draw.text((text_x, text_y), text, font=font, fill=txt_color)
return image
# 位置暂时由系统决定
def generate_image(bac_img, title,a,b,c,d,e,f, #-- 当前文本行内字数可调,宽度可调 words_curline or 文本宽度
font_title, sz1, title_x, title_y, color1, # for title
font_subtt, sz2, subtt_x, subtt_y, color2,
font_txt, sz3, txt_x, color3, bac_color):
if bac_img is None:
bac_img = "./kaobianBottem.jpeg"
bing_post = "bingpost/"
spacing = 20
# imgs_ = os.listdir(bing_post)
# imgs_ = [i for i in imgs_ if i.endswith("png")]
# ch_img = random.choice(imgs_)
# front_img = os.path.join(bing_post, ch_img)
front_img = None
postcard=myPost(front_img=front_img, img = bac_img)
width, height = postcard.get_width_height()
print(f"width, height :{width} {height}")
# 前景图, 待开放参数控制
# postcard.drawFrontground()
# 放置标题 + 字体字号
spacing=20
# --理想总行字数
words, rows = postcard.getLinesCount(sz=sz1, spacing=spacing)
words = (width - title_x) / ( sz1 + spacing)
words = int(words) + 1
title_text = textwrap.wrap(title, width=words)
title_text = [i.center(words) for i in title_text]
postcard.postBoxText(title_text, font=font_title, sz = sz1,
x=title_x,
# x=0,
y=title_y, color = color1, spacing=spacing, ali = "center",
bac_color=None)
# 子标题 + 内容的处理 + 每行字数
# x=40
y = subtt_y # 标题与剩下内容高度
#- -- 扣除起始位置 能放字数 ---
words = int((width) / sz3)
for k,contents in enumerate([a,b,c,d,e,f]):
if len(contents) < 1:
continue
lines = contents.split("。")
if len(lines) < 2:
continue
sub_title = lines[0]
sub_texts = "。".join(lines[1:])
words = int((width - txt_x) / sz3) - 2
sub_text = textwrap.wrap(sub_texts, width=words)
# sub_text = [i.center(words) for i in sub_text]
# -----文本框效果--------
# draw.rectangle((x, y, x + w, y + h), fill=bac_color)
postcard.postBoxText([sub_title], font=font_subtt, sz = sz2,
x=subtt_x, y=y, color = color2, spacing=spacing,
ali = "left" ,bac_color=bac_color)
y += int(sz2*2.5)
postcard.postBoxText(sub_text, font=font_txt, sz = sz3,
x=txt_x, y=y, color = color3, spacing=spacing,
ali = "left", bac_color=None)
y += (sz3 + spacing) * len(sub_text) + 50
return postcard.get_res()
def generate_template( pre_img, input_image, mt_name,
font_title, sz1, title_x, title_y, color1,
font_subtt, sz2, subtt_x, subtt_y, color2,
font_txt, sz3, txt_x, color3, bac_color):
if pre_img is None:
print("没调试好,不能保存")
return None
if type(pre_img) is np.ndarray:
template_img = f"./templates/{mt_name}.png"
template_img_preview = f"./templates/{mt_name}.jpg"
print("保存图片", template_img)
pil = Image.fromarray(input_image)
pil_2 = Image.fromarray(pre_img)
pil_2.save(template_img_preview)
pil.save(template_img)
print("开始保存模板")
# 保存模板预览效果
template_name = f"./templates/{mt_name}.csv"
name = ["template_img","font_title", "sz1", "title_x", "title_y", "color1",
"font_subtt", "sz2", "subtt_x", "subtt_y", "color2",
"font_txt", "sz3", "txt_x", "color3", "bac_color"]
value = [[template_img, font_title, sz1, title_x, title_y, color1,
font_subtt, sz2, subtt_x, subtt_y, color2,
font_txt, sz3, txt_x, color3, bac_color]]
record = pd.DataFrame(data=value, columns=name)
record.to_csv(template_name, index=False)
return [os.path.join(templates_path,i) for i in os.listdir(templates_path) if i.endswith("jpg")]
def load_template(mt_name):
template_name = f"./templates/{mt_name}.csv"
template_img = f"./templates/{mt_name}.png"
if not os.path.exists(template_name):
print("error on dealing this template name :", mt_name)
return None
template_df = pd.read_csv(template_name)
# print(template_df)
# return ["font_title", 12, 1, 1, "color1",
# "font_subtt", 12, 123, 1, "color2",
# "font_txt", 123, 12, "color3"]
# res = [template_img]
# res.extend()
res = list(template_df.values[0])
return res
# def change_textbox(choice):
# #根据不同输入对输出控件进行更新
# if choice == "short":
# return gr.update(lines=2, visible=True, value="Short story: ")
# elif choice == "long":
# return gr.update(lines=8, visible=True, value="Long story...")
# else:
# return gr.update(visible=False)
# with gr.Blocks() as demo:
# radio = gr.Radio(
# ["short", "long", "none"], label="Essay Length to Write?"
# )
# text = gr.Textbox(lines=2, interactive=True)
# radio.change(fn=change_textbox, inputs=radio, outputs=text)
# demo.launch()
key_index = ["bm_sj","fee_sj","ks_sj","zkz_sj"]
def generate_mv(bac_img, title, a,b,c,d,e,f, sz1, sz2, sz3, spacing, color1, color2):
global movies, imgs_cur
bing_dir = "./bingpost"
front_imgs =[os.path.join(bing_dir,i) for i in os.listdir("./bingpost") if i.endswith(".png")]
front_img = random.choice(front_imgs)
if bac_img is None:
bac_img = "./kaobianBottem.jpeg"
imge_dir = "imgpost"
fps = 1
image_dur = 3
movie_dir = "movie_output"
msg = []
new_title = title.replace('\n', "").replace('”', "").replace('“', "").replace(' ', "")
output_wav = f"audio_output/{new_title}.wav"
tts_cmd = f'edge-tts --voice zh-CN-XiaoxiaoNeural --rate=+10% --text "{title}" --write-media {output_wav} 2>&1 >/dev/null'
_m = os.popen(tts_cmd).read()
msg.append(_m)
# image
audio_file = AudioFileClip(output_wav)
movie_file = f"{movie_dir}/{new_title}.mp4"
img_files = []
mv_image_files = []
for k,lines in enumerate([title,a,b,c,d]):
k = key_index[k]
if not lines:
# 这个关键信息没有,跳过
continue
if len(lines) < 2:
continue
lines = lines.split("\n")
filename = f"{k}_{new_title}.png"
filename = os.path.join(imge_dir, filename)
img_files.append(filename)
# --- how long a image last display
for i in range(image_dur):
mv_image_files.append(filename)
img = generatePost(lines=lines,front_img = front_img, bac_img = bac_img, fn_name = filename)
# clip_img = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(img_files, fps=fps) #durations=audio_file.duration ) #
if len(img_files) < 1:
print("error, this url not get a valid key info:{new_title},url:{url_}")
return "","",""
clip_img = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(mv_image_files, fps=fps, durations=audio_file.duration ) #
clip_img = clip_img.set_audio(audio_file)
clip_img.write_videofile(movie_file, fps=fps)#, audio_codec="aac")
print(movie_file, ":done")
movies = [os.path.join(mv_path,i) for i in os.listdir(mv_path) if i.endswith("mp4")]
# imgs = [os.path.join(img_path,i) for i in os.listdir(mv_path) if i.endswith("png")]
imgs_cur = img_files
return movie_file, img_files
def exit_func():
driver.close()
time.sleep(3)
exit(1)
# def refresh_template():
# global templates_name
# templates_name = [i.strip(templates_path).strip(".csv") for i in templates]
# return templates_name
# 登录抖音
def loginDouyin():
url = 'https://creator.douyin.com/'
hm.set_driver(driver) # 给它一个selnuim driver
hm.go_to(url)
# driver.get_screenshot_as_file("1.png")
print("-------------------请扫描二维码登录抖音创作者中心-------------------")
hm.click(hm.Text("登录"))
time.sleep(1)
hm.click(hm.Text("确认"))
time.sleep(1)
qr_element = driver.find_element_by_class_name("qrcode-image")
qr_element.click()
qr_element.screenshot("qr.png")
return "qr.png"
def run_save_cookie(account_name):
cookie_fns.append(account_name)
cookie_file_name = cookie_f.format(account_name)
save_cookie(driver, cookie_file_name)
gr.Dropdown.update(choices=account_fn, value=cookie_fns)
return "succ"
input_image_, font_title_, sz1_, title_x_, title_y_, color1_, \
font_subtt_, sz2_, subtt_x_, subtt_y_, color2_, \
font_txt_, sz3_, txt_x_, color3_, bac_color_ = load_template("专有")
# 构建Blocks上下文 =======================================================================
with gr.Blocks() as demo:
with gr.Tabs():
# --------------generate movie -------------
with gr.TabItem("生成 & 预览"):
gr.Markdown(f"# {VIPtitle}")
gr.Markdown(f"{description}")
with gr.Row(): # 行排列
with gr.Column(): # 列排列
title = gr.Textbox("朝天区2023招聘事业单位工作人员公告",label="标题",interactive=True)
a = gr.Textbox("标题1。内容",label="a")
b = gr.Textbox(lines=2, value = "报名时间。2023年3月10日至3月17日24:00。", label="b",interactive=True)
c = gr.Textbox(lines=2, value = "子标题1。笔试分别于2023年4月8日", label="c",interactive=True)
d = gr.Textbox(lines=2, value = " ", label="d",interactive=True)
e = gr.Textbox(lines=2, value = " ", label="e",interactive=True)
f = gr.Textbox(lines=2, value = " ", label="f",interactive=True)
# movie_file = gr.Video(exam_video,label="movie")
with gr.Column():
# -- 输入背景图底图 作为画布 --
input_image = gr.Image(input_image_, label = "背景图, input",interactive=True)
title_x = gr.Slider(1, WIDTH, label = "标题左右移动", value=title_x_, step = 5)
title_y = gr.Slider(1, HEIGHT, label = "标题上下移动", value=title_y_, step = 5)
font_title = gr.Dropdown(choices = font_list, label = "标题字体",
value = font_title_)
sz1 = gr.Slider(1, 100, label = "标题大小", value=sz1_, step = 5)
color1 = gr.Textbox(color1_, label = "标题颜色")
bac_color = gr.Textbox(bac_color_, label = "文本框颜色 空不设置文本框")
with gr.Column():
# -- 子标题
font_subtt = gr.Dropdown(choices = font_list, label = "子标题字体", value = font_subtt_)
sz2 = gr.Slider(1, 100, label = "subTitleSZ", value=sz2_, step = 5)
subtt_x = gr.Slider(1, WIDTH, label = "子标题左右-->", value=subtt_x_, step = 5)
subtt_y = gr.Slider(1, HEIGHT, label = "子标题 上下 ^ v", value=subtt_y_, step = 5)
color2 = gr.Textbox(color2_, label = "子标题颜色")
font_txt = gr.Dropdown(choices = font_list, label = "文本字体", value = font_txt_)
sz3 = gr.Slider(1, 100, label = "wordSize", value=sz3_, step = 5)
txt_x = gr.Slider(1, WIDTH, label = "内容位置_x", value=txt_x_, step = 5)
color3 = gr.Textbox(color3_, label = "文字颜色")
with gr.Row():
with gr.Column(): # ----按钮控件------
pre_img_bt = gr.Button("预览")
record_template = gr.Button("导出模板")
mt_name = gr.Textbox("模板_v1",label="导出模板必填名字")
# font_txt = gr.Dropdown(choices = font_list, label = "文本字体", value = "fonts/simsun.ttc")
mt_selected = gr.Dropdown(choices = templates_name, label = "选择模板载入")
load_mt = gr.Button("载入模板参数")
# submit = gr.Button("生成")
# account_fn = gr.Dropdown(choices=cookie_fns, label = "账号选择", value = "抖音广东人事考试")
# with gr.Column():
pre_img2 = gr.Image(label="生成结果预览", interactive=False)
with gr.Row():
gallery = gr.Gallery(
value = preview_templates,
label="preview", show_label=True, elem_id="gallery"
).style(columns=[3], rows=[2], object_fit="contain", height="auto")
# mv_files = gr.Files(movies, label="movies")
# img_files = gr.Files(imgs_cur, label="movie_imgs")
with gr.TabItem("生成&发布"):
gr.Markdown(f"{description}")
with gr.Row(): # 行排列
with gr.Column(): # 列排列
title1 = gr.Textbox("朝天区2023招聘事业单位工作人员公告",label="标题")
a1 = gr.Textbox("xxxx",label="a")
b1 = gr.Textbox(lines=2, value = "报名时间。2023年3月10日至3月17日24:00。", label="b")
c1 = gr.Textbox(lines=2, value = "缴费时间。2023年05月27日 ", label="c")
d1 = gr.Textbox(lines=2, value = "子标题1。笔试分别于2023年4月8日", label="d")
e1 = gr.Textbox(lines=2, value = "子标题2。广元人事考试网打印本人准考证。", label="e")
f1 = gr.Textbox(lines=2, value = "子标题3。 见准考证。", label="f")
with gr.Column():
# 上传做好的图进行生成
input_image_2 = gr.Image(background_img, label = "背景图, input",interactive=True)
with gr.Row():
with gr.Column(): # ----按钮控件------
post_img_bt = gr.Button("test_post")
refresh_template_bt = gr.Button("刷新模板")
# mt_name = gr.Textbox("模板_v1",label="导出模板必填名字")
mt_name_selected = gr.Dropdown(choices = templates_name, label = "选择模板进行生产")
# pre_img2 = gr.Image(label="生成结果预览", interactive=False)
with gr.TabItem("todo内嵌浏览器pyqt html"):
mp = gr.HTML(html, elem_id="coords", visible=True)
pass
pre_img_bt.click(fn=generate_image, inputs=[input_image, title,a,b,c,d,e,f,
font_title, sz1, title_x, title_y, color1,
font_subtt, sz2, subtt_x, subtt_y, color2,
font_txt, sz3, txt_x, color3, bac_color],
outputs=[pre_img2])
record_template.click(fn=generate_template, inputs=[pre_img2, input_image, mt_name,
font_title, sz1, title_x, title_y, color1,
font_subtt, sz2, subtt_x, subtt_y, color2,
font_txt, sz3, txt_x, color3, bac_color],
outputs=[gallery])
load_mt.click(fn=load_template,
inputs = [mt_selected],
outputs=[input_image, font_title, sz1, title_x, title_y, color1,
font_subtt, sz2, subtt_x, subtt_y, color2,
font_txt, sz3, txt_x, color3, bac_color])
# refresh_template_bt.click(fn=refresh_template, inputs=None, outputs=[templates_name])
# template_params = []
# post_img_bt.click(inputs = [title, a,b,c,d,e,f]) # 用于追加模板参数,简洁版本
# submit.click(fn=generate_mv, inputs=[title, a,b,c,d],
# outputs=[img_files])
# outputs=[movie_file, img_files])
# exit_.click(fn=exit_func)
# login_.click(fn=loginDouyin, outputs=[login_qr])
# login_save.click(fn=run_save_cookie, inputs = [account_name_new])
# post_.click(fn=mySendDouyin, inputs = [account_fn, movie_file])
# 绑定clear点击函数
# clear.click(fn=clear_input, inputs=[], outputs=[context, question, answer, score])
if __name__ == "__main__":
demo.queue().launch()
print("run from current ")