Spaces:
Running
Running
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import os, tempfile, zipfile, multiprocessing
|
| 3 |
+
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
|
| 4 |
+
from moviepy.editor import VideoFileClip
|
| 5 |
+
|
| 6 |
+
def extract_clip(args):
|
| 7 |
+
in_path, start, end, out_path = args
|
| 8 |
+
ffmpeg_extract_subclip(in_path, start, end, targetname=out_path)
|
| 9 |
+
return out_path
|
| 10 |
+
|
| 11 |
+
def split_video(video_data, chunks):
|
| 12 |
+
if not video_data:
|
| 13 |
+
return [None] * 10, None
|
| 14 |
+
tmp = tempfile.mkdtemp()
|
| 15 |
+
in_path = os.path.join(tmp, "input.mp4")
|
| 16 |
+
with open(in_path, "wb") as f: f.write(video_data)
|
| 17 |
+
clip = VideoFileClip(in_path)
|
| 18 |
+
tot = clip.duration
|
| 19 |
+
seg = tot / chunks
|
| 20 |
+
tasks = [(in_path, i * seg, tot if i == chunks - 1 else (i + 1) * seg, os.path.join(tmp, f"chunk_{i+1}.mp4"))
|
| 21 |
+
for i in range(chunks)]
|
| 22 |
+
with multiprocessing.Pool() as pool:
|
| 23 |
+
parts = pool.map(extract_clip, tasks)
|
| 24 |
+
clip.close()
|
| 25 |
+
zip_path = os.path.join(tmp, "chunks.zip")
|
| 26 |
+
with zipfile.ZipFile(zip_path, "w") as z:
|
| 27 |
+
for p in parts:
|
| 28 |
+
z.write(p, os.path.basename(p))
|
| 29 |
+
return parts, zip_path
|
| 30 |
+
|
| 31 |
+
def split_interface(video_data, chunks):
|
| 32 |
+
parts, zip_path = split_video(video_data, chunks)
|
| 33 |
+
vids = [gr.update(value=parts[i], visible=True) if i < len(parts)
|
| 34 |
+
else gr.update(visible=False) for i in range(10)]
|
| 35 |
+
return vids + [zip_path]
|
| 36 |
+
|
| 37 |
+
with gr.Blocks() as demo:
|
| 38 |
+
gr.Markdown("# Equal Chunk Video Splitter\nUpload a video, choose the number of chunks, preview them, and download a ZIP.")
|
| 39 |
+
with gr.Row():
|
| 40 |
+
with gr.Column(scale=1):
|
| 41 |
+
vid_in = gr.File(label="Upload Video", file_types=["video"], type="binary")
|
| 42 |
+
chunks_slider = gr.Slider(1, 10, value=5, step=1, label="Chunks")
|
| 43 |
+
split_btn = gr.Button("Split Video")
|
| 44 |
+
with gr.Column(scale=2):
|
| 45 |
+
zip_out = gr.File(label="Download ZIP")
|
| 46 |
+
previews = [gr.Video(label=f"Chunk {i+1}", visible=False, height=150) for i in range(10)]
|
| 47 |
+
split_btn.click(split_interface, [vid_in, chunks_slider], previews + [zip_out])
|
| 48 |
+
|
| 49 |
+
if __name__ == '__main__':
|
| 50 |
+
demo.launch()
|