| import time |
| import random |
| import os |
| import gradio as gr |
| import pandas as pd |
| import textwrap |
|
|
| import traceback |
|
|
| |
| |
| |
| import helium as hm |
| |
| |
| from transformers import * |
|
|
| import pandas as pd |
| import os |
| import random |
| |
| 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}") |
| |
| mv_path = "./movie_output" |
| img_path = "./imgpost" |
| font_path = "./fonts" |
| |
| |
| |
| 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 |
|
|
| |
| |
| |
| |
| description = "URL--> 爬取-->解析--> 音频--> 图片--> 视频" |
|
|
| |
| |
| |
| |
| |
| 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前登录报名网站打印准考证" |
| ], |
| ] |
|
|
| |
| |
| 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) |
| |
| 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, |
| 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 bac_img is None: |
| bac_img = "./kaobianBottem.jpeg" |
| bing_post = "bingpost/" |
| spacing = 20 |
| |
| |
| |
| |
| front_img = None |
| postcard=myPost(front_img=front_img, img = bac_img) |
| width, height = postcard.get_width_height() |
| print(f"width, height :{width} {height}") |
| |
| |
| |
| 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, |
| |
| y=title_y, color = color1, spacing=spacing, ali = "center", |
| bac_color=None) |
|
|
| |
| |
| 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) |
| |
| |
| |
| 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) |
| |
| |
| |
| |
| |
| |
| res = list(template_df.values[0]) |
| return res |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| 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) |
| |
| 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) |
| |
| 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) |
|
|
| |
| 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) |
| print(movie_file, ":done") |
| movies = [os.path.join(mv_path,i) for i in os.listdir(mv_path) if i.endswith("mp4")] |
| |
| imgs_cur = img_files |
| return movie_file, img_files |
|
|
| def exit_func(): |
| driver.close() |
| time.sleep(3) |
| exit(1) |
|
|
| |
| |
| |
| |
| |
| |
| def loginDouyin(): |
| url = 'https://creator.douyin.com/' |
| hm.set_driver(driver) |
| hm.go_to(url) |
| |
| 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("专有") |
| |
| with gr.Blocks() as demo: |
| with gr.Tabs(): |
| |
| 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) |
| |
| |
| 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="导出模板必填名字") |
| |
| mt_selected = gr.Dropdown(choices = templates_name, label = "选择模板载入") |
| load_mt = gr.Button("载入模板参数") |
| |
| |
| |
| 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") |
| |
| |
| |
|
|
| 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_selected = gr.Dropdown(choices = templates_name, label = "选择模板进行生产") |
| |
|
|
| 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]) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| if __name__ == "__main__": |
| demo.queue().launch() |
| print("run from current ") |
|
|