Vo Hoang Minh commited on
Commit
cc480cf
·
1 Parent(s): a7b9092
Files changed (1) hide show
  1. app.py +50 -36
app.py CHANGED
@@ -1,51 +1,65 @@
1
- import gradio as gr, json, os, subprocess, tempfile
 
2
 
3
- # Load tất cả effect từ assets/
4
- effects = {}
5
- for f in os.listdir("assets"):
6
- if f.endswith(".json"):
7
- with open(f"assets/" + f, encoding="utf-8") as j:
8
- for e in json.load(j).get("effects", []):
9
- effects[e["name"]] = e["command"]
 
10
 
11
- def update_command(name):
12
- return effects.get(name, "")
13
 
14
- def apply_effect(file, command, output_type):
15
- if file is None:
16
- return "❌ Chưa chọn file", None, ""
17
-
18
- ext = ".gif" if output_type == "GIF" else ".mp4"
19
- out_path = tempfile.NamedTemporaryFile(suffix=ext, delete=False).name
20
 
21
- # Build command
22
- cmd = ["ffmpeg", "-y", "-i", file.name] + command.split() + ["-preset", "ultrafast", out_path]
23
- log = " ".join(cmd)
 
 
 
 
 
24
 
25
- subprocess.run(cmd, check=True)
 
 
 
 
26
 
27
- return f"✅ Đã tạo hiệu ứng", out_path, log
 
 
 
 
 
 
 
 
28
 
29
  with gr.Blocks() as app:
30
- gr.Markdown("🎞️ **Ứng dụng hiệu ứng video từ JSON (FFmpeg)**")
31
 
32
- with gr.Row():
33
- f = gr.File(label="Ảnh hoặc Video")
34
- output_type = gr.Radio(["MP4", "GIF"], value="MP4", label="Loại đầu ra")
 
 
 
 
35
 
36
  with gr.Row():
37
- effect_input = gr.Textbox(label="Nhập tên hiệu ứng")
38
- effect_dropdown = gr.Dropdown(choices=list(effects), label="Hoặc chọn hiệu ứng")
39
-
40
- command_box = gr.Textbox(label="Lệnh FFmpeg sẽ chạy", lines=2)
41
- log_box = gr.Textbox(label="Lệnh đã chạy", lines=2, interactive=False)
42
 
43
- run_btn = gr.Button("Tạo hiệu ứng")
44
- out_msg = gr.Textbox(label="Trạng thái")
45
- out_video = gr.Video()
46
 
47
- effect_input.change(update_command, effect_input, command_box)
48
- effect_dropdown.change(update_command, effect_dropdown, command_box)
49
- run_btn.click(apply_effect, [f, command_box, output_type], [out_msg, out_video, log_box])
 
50
 
51
  app.launch()
 
1
+ import gradio as gr
2
+ import json, os, subprocess, tempfile, shlex, mimetypes
3
 
4
+ def load_effects(path="assets"):
5
+ effects = {}
6
+ for file in os.listdir(path):
7
+ if file.endswith(".json"):
8
+ with open(os.path.join(path, file), encoding="utf-8") as f:
9
+ for e in json.load(f).get("effects", []):
10
+ effects[e["name"]] = e["command"]
11
+ return effects
12
 
13
+ EFFECTS = load_effects()
 
14
 
15
+ def get_command(name): return EFFECTS.get(name, "")
 
 
 
 
 
16
 
17
+ def run_ffmpeg(input_path, command_str, output_ext):
18
+ out = tempfile.NamedTemporaryFile(suffix=output_ext, delete=False).name
19
+ args = ["ffmpeg", "-y", "-i", input_path] + shlex.split(command_str) + ["-preset", "ultrafast", out]
20
+ try:
21
+ subprocess.run(args, check=True)
22
+ return "✅ Hiệu ứng đã tạo", out, " ".join(args)
23
+ except subprocess.CalledProcessError as e:
24
+ return f"❌ Lỗi FFmpeg: {e}", None, " ".join(args)
25
 
26
+ def apply_effect(file, command, out_type):
27
+ if not file:
28
+ return "❌ Chưa chọn file", None, ""
29
+ ext = ".gif" if out_type == "GIF" else ".mp4"
30
+ return run_ffmpeg(file.name, command, ext)
31
 
32
+ def preview_media(file):
33
+ if not file:
34
+ return None, None
35
+ mime, _ = mimetypes.guess_type(file.name)
36
+ if mime and mime.startswith("image"):
37
+ return file.name, None
38
+ elif mime and mime.startswith("video"):
39
+ return None, file.name
40
+ return None, None
41
 
42
  with gr.Blocks() as app:
43
+ gr.Markdown("🎞️ **Hiệu ứng video bằng FFmpeg từ file JSON**")
44
 
45
+ f = gr.File(label="Tệp ảnh/video", file_types=["image", "video"])
46
+ t = gr.Radio(["MP4", "GIF"], value="MP4", label="Loại đầu ra")
47
+ name_input = gr.Textbox(label="Nhập tên hiệu ứng")
48
+ name_select = gr.Dropdown(choices=list(EFFECTS), label="Hoặc chọn hiệu ứng")
49
+ cmd_box = gr.Textbox(label="Lệnh FFmpeg", lines=2)
50
+ log_box = gr.Textbox(label="Log", lines=2, interactive=False)
51
+ msg = gr.Textbox(label="Trạng thái")
52
 
53
  with gr.Row():
54
+ preview_img = gr.Image(label="Ảnh đã chọn", visible=False)
55
+ preview_vid = gr.Video(label="Video đã chọn", visible=False)
 
 
 
56
 
57
+ out = gr.Video(label="Kết quả")
58
+ btn = gr.Button("Tạo hiệu ứng")
 
59
 
60
+ name_input.change(get_command, name_input, cmd_box)
61
+ name_select.change(get_command, name_select, cmd_box)
62
+ f.change(preview_media, f, [preview_img, preview_vid])
63
+ btn.click(apply_effect, [f, cmd_box, t], [msg, out, log_box])
64
 
65
  app.launch()