aibb / app.py
zdxpan's picture
Rename mm.py to app.py
40a087c
raw
history blame
No virus
23.2 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 get_content_from_driver(task_link, content=None):
driver = getDriver()
hm.set_driver(driver) # 给它一个selnuim driver
if content:
pass
hm.go_to(task_link)
print("hm.go_to(task_link)")
time.sleep(1)
items_ = driver.find_elements_by_xpath("//p")
items_ = [i.text for i in items_ if i.text != ""]
context_to_label = "\n".join(items_)
doc = extract_from_driver(driver)
doc["url"] = task_link
doc["content"] = context_to_label
n_bm_sj,_ = custom_predict(context = context_to_label, question="报名时间")
n_fee_sj,_ = custom_predict(context = context_to_label, question="缴费时间")
n_ks_sj,_ = custom_predict(context = context_to_label, question="考试时间")
n_zkz_sj,_ = custom_predict(context = context_to_label, question="准考证时间")
need = [doc["title"],doc["zwlx"], doc["zwk_sheng"], doc["zwk_diqu"],
doc["tidy_bm_sj"], doc["tidy_fee_sj"], doc["tidy_ks_sj"], doc["tidy_zkz_sj"],context_to_label,
n_bm_sj, n_fee_sj, n_ks_sj, n_zkz_sj
]
return need
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)
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) / 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"
def mySendDouyin(cookie_fn, movie_file):
driver = getDriver()
# new_title = title.replace('\n', "").replace('”', "").replace('“', "").replace(' ', "")
# movie_file = f"{movie_dir}/{new_title}.mp4"
print(f"in mySendDouyin func: try send {movie_file}")
if not os.path.exists(movie_file):
raise f"movie_file not exists"
print(movie_file)
# senDouyin(account_name = cookie_fn, title = title, movie_path = movie_file, loc = "北京")
for i in range(5):
try:
senDouyin(driver = driver, account_name = cookie_fn, title = title, movie_path = movie_file, loc = "北京")
print(f"accunt {cookie_fn} 发布 {movie_file} succ")
break
except Exception as e:
traceback.print_exc()
driver.get_screenshot_as_file("1.png")
print("---mySendDouyin faild, continue try--")
continue
return "succ"
# 构建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("xxxx",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 = "缴费时间。2023年05月27日 ", label="c",interactive=True)
d = gr.Textbox(lines=2, value = "子标题1。笔试分别于2023年4月8日", label="d",interactive=True)
e = gr.Textbox(lines=2, value = "子标题2。广元人事考试网打印本人准考证。", label="e",interactive=True)
f = gr.Textbox(lines=2, value = "子标题3。 见准考证。", label="f",interactive=True)
# movie_file = gr.Video(exam_video,label="movie")
with gr.Column():
# -- 输入背景图底图 作为画布 --
input_image = gr.Image(background_img, label = "背景图, input",interactive=True)
title_x = gr.Slider(1, WIDTH, label = "标题左右移动", value=60, step = 5)
title_y = gr.Slider(1, HEIGHT, label = "标题上下移动", value=320, step = 5)
font_title = gr.Dropdown(choices = font_list, label = "标题字体",
value = "fonts/特创易新恒LOGO美黑.ttf")
sz1 = gr.Slider(1, 100, label = "标题大小", value=80, step = 5)
color1 = gr.Textbox("blue", label = "标题颜色")
bac_color = gr.Textbox("blue", label = "文本框颜色 空不设置文本框")
with gr.Column():
# -- 子标题
font_subtt = gr.Dropdown(choices = font_list, label = "子标题字体", value = "fonts/吉页颉润体简.ttf")
sz2 = gr.Slider(1, 100, label = "subTitleSZ", value=55, step = 5)
subtt_x = gr.Slider(1, WIDTH, label = "子标题左右-->", value=80, step = 5)
subtt_y = gr.Slider(1, HEIGHT, label = "子标题 上下 ^ v", value=780, step = 5)
color2 = gr.Textbox("#007000", label = "子标题颜色")
font_txt = gr.Dropdown(choices = font_list, label = "文本字体", value = "fonts/simsun.ttc")
sz3 = gr.Slider(1, 100, label = "wordSize", value=40, step = 5)
txt_x = gr.Slider(1, WIDTH, label = "内容位置_x", value=80, step = 5)
color3 = gr.Textbox("#101010", 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("登录账号"):
with gr.Row():
login_ = gr.Button("登录抖音")
login_save = gr.Button("登录完成保存")
with gr.Row():
account_name_new = gr.Textbox(label="新建账号")
login_qr = gr.Image("qr.png", shape=(200, 200), label="登录账号")
# gr.Dropdown.update(choices=cookie_fns, value=cookie_fn)
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(share=True)
print("run from current ")