Spaces:
Running
Running
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import zipfile
|
3 |
+
import io
|
4 |
+
import tempfile
|
5 |
+
import requests
|
6 |
+
from moviepy.editor import ImageSequenceClip, concatenate_videoclips, ImageClip
|
7 |
+
import gradio as gr
|
8 |
+
from gradio_client import Client, handle_file
|
9 |
+
|
10 |
+
def download_file(file_url):
|
11 |
+
response = requests.get(file_url)
|
12 |
+
response.raise_for_status() # 确保请求成功
|
13 |
+
return response.content
|
14 |
+
|
15 |
+
def get_images_from_api(uploaded_file):
|
16 |
+
client = Client("https://pptx2jpgapi.webgpu.click/")
|
17 |
+
result = client.predict(
|
18 |
+
uploaded_file=handle_file(uploaded_file.name), # 使用 handle_file 处理上传的文件
|
19 |
+
mode="Convert each slide to a separate JPG", # 固定模式
|
20 |
+
api_name="/convert_pptx_to_jpg"
|
21 |
+
)
|
22 |
+
|
23 |
+
print(result)
|
24 |
+
print(result[0]) #
|
25 |
+
|
26 |
+
# file_url = f"https://pptx2jpgapi.webgpu.click/file={result[0]}"
|
27 |
+
|
28 |
+
# print(file_url)
|
29 |
+
|
30 |
+
# # 下载ZIP文件内容
|
31 |
+
# zip_content = download_file(file_url)
|
32 |
+
|
33 |
+
# 创建临时目录
|
34 |
+
temp_dir = tempfile.mkdtemp()
|
35 |
+
|
36 |
+
# 解压返回的zip文件
|
37 |
+
# with zipfile.ZipFile(io.BytesIO(zip_content), 'r') as zip_ref:
|
38 |
+
# zip_ref.extractall(temp_dir)
|
39 |
+
|
40 |
+
with zipfile.ZipFile(result[0], 'r') as zip_ref:
|
41 |
+
zip_ref.extractall(temp_dir)
|
42 |
+
|
43 |
+
return temp_dir
|
44 |
+
|
45 |
+
def apply_transition(clip1, clip2, transition_type, transition_time):
|
46 |
+
if transition_type == "crossfade":
|
47 |
+
return clip1.crossfadeout(transition_time), clip2.crossfadein(transition_time)
|
48 |
+
elif transition_type == "fadeout":
|
49 |
+
return clip1.fadeout(transition_time), clip2
|
50 |
+
elif transition_type == "fadein":
|
51 |
+
return clip1, clip2.fadein(transition_time)
|
52 |
+
elif transition_type == "none":
|
53 |
+
return clip1, clip2
|
54 |
+
else:
|
55 |
+
raise ValueError(f"Unsupported transition type: {transition_type}")
|
56 |
+
|
57 |
+
def images_to_video(image_folder, fps=24, display_time=3, transition_time=1, transition_type="none"):
|
58 |
+
# 获取所有jpg文件并按名称排序
|
59 |
+
image_files = sorted([os.path.join(image_folder, img) for img in os.listdir(image_folder) if img.endswith(".jpg")])
|
60 |
+
if not image_files:
|
61 |
+
raise ValueError("No jpg files found in the directory.")
|
62 |
+
|
63 |
+
clips = []
|
64 |
+
for img_path in image_files:
|
65 |
+
img_clip = ImageClip(img_path, duration=display_time)
|
66 |
+
|
67 |
+
# 调整图片尺寸,保持比例,最短边为720
|
68 |
+
w, h = img_clip.size
|
69 |
+
if w < h:
|
70 |
+
img_clip = img_clip.resize(width=720)
|
71 |
+
else:
|
72 |
+
img_clip = img_clip.resize(height=720)
|
73 |
+
|
74 |
+
clips.append(img_clip)
|
75 |
+
|
76 |
+
# 添加过渡效果
|
77 |
+
final_clips = []
|
78 |
+
for i in range(len(clips) - 1):
|
79 |
+
clip1, clip2 = apply_transition(clips[i], clips[i+1], transition_type, transition_time)
|
80 |
+
final_clips.append(clip1)
|
81 |
+
final_clips.append(clip2)
|
82 |
+
final_clips.append(clips[-1])
|
83 |
+
|
84 |
+
video = concatenate_videoclips(final_clips, method="compose")
|
85 |
+
video_path = os.path.join(tempfile.gettempdir(), "output_video.mp4")
|
86 |
+
video.write_videofile(video_path, fps=fps)
|
87 |
+
return video_path
|
88 |
+
|
89 |
+
def generate_video(uploaded_file, display_time, transition_type, transition_time):
|
90 |
+
image_folder = get_images_from_api(uploaded_file)
|
91 |
+
video_path = images_to_video(image_folder, display_time=display_time, transition_time=transition_time, transition_type=transition_type)
|
92 |
+
return video_path
|
93 |
+
|
94 |
+
# Gradio interface
|
95 |
+
with gr.Blocks(analytics_enabled=False,title="PPTX to Video Converter") as demo:
|
96 |
+
gr.Markdown("""
|
97 |
+
# PPTX to Video Converter
|
98 |
+
|
99 |
+
## Convert Your PPTX Files to Videos Easily
|
100 |
+
This tool allows you to convert PPTX files to video format. You can set the display time for each slide, choose different transition effects, and generate a complete video with transitions.
|
101 |
+
|
102 |
+
### How to Use
|
103 |
+
1. Upload your PPTX file.
|
104 |
+
2. Set the display time for each slide.
|
105 |
+
3. Choose a transition effect type.
|
106 |
+
4. Set the transition time.
|
107 |
+
5. Click the "Generate Video" button, and wait for the video to be generated and displayed on the right.
|
108 |
+
""")
|
109 |
+
with gr.Row():
|
110 |
+
with gr.Column():
|
111 |
+
uploaded_file = gr.File(label="Upload PPTX File", file_types=[".pptx"])
|
112 |
+
display_time = gr.Slider(label="Image Display Time (seconds)", minimum=1, maximum=5, step=1, value=3, info="Set the display time for each slide")
|
113 |
+
transition_type = gr.Radio(["crossfade", "fadeout", "fadein", "none"], label="Transition Type", value="none", info="Choose the type of transition effect")
|
114 |
+
transition_time = gr.Slider(label="Transition Time (seconds)", minimum=1, maximum=2, step=1, value=1, info="Set the transition time")
|
115 |
+
generate_button = gr.Button("Generate Video")
|
116 |
+
with gr.Column():
|
117 |
+
video_output = gr.Video(label="Generated Video")
|
118 |
+
|
119 |
+
generate_button.click(
|
120 |
+
fn=generate_video,
|
121 |
+
inputs=[uploaded_file, display_time, transition_type, transition_time],
|
122 |
+
outputs=video_output
|
123 |
+
)
|
124 |
+
|
125 |
+
# 运行Gradio应用
|
126 |
+
if __name__ == "__main__":
|
127 |
+
demo.launch(show_error=True)
|