FeilongTang commited on
Commit
14590e3
·
1 Parent(s): 3ba51be

Add minimal ffprobe-based codec inspector

Browse files
Files changed (2) hide show
  1. app.py +83 -0
  2. packages.txt +1 -0
app.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import shutil
4
+ import subprocess
5
+
6
+ import gradio as gr
7
+
8
+
9
+ def probe_video(video_path):
10
+ if not video_path:
11
+ return "Please upload a video.", None
12
+
13
+ if shutil.which("ffprobe") is None:
14
+ return (
15
+ "ffprobe not found. Add `ffmpeg` to packages.txt at the repo root.",
16
+ None,
17
+ )
18
+
19
+ try:
20
+ result = subprocess.run(
21
+ [
22
+ "ffprobe",
23
+ "-v", "quiet",
24
+ "-print_format", "json",
25
+ "-show_format",
26
+ "-show_streams",
27
+ video_path,
28
+ ],
29
+ capture_output=True,
30
+ text=True,
31
+ check=True,
32
+ )
33
+ except subprocess.CalledProcessError as e:
34
+ return f"ffprobe failed:\n{e.stderr}", None
35
+
36
+ info = json.loads(result.stdout)
37
+ fmt = info.get("format", {}) or {}
38
+ streams = info.get("streams", []) or []
39
+ v = next((s for s in streams if s.get("codec_type") == "video"), {})
40
+ a = next((s for s in streams if s.get("codec_type") == "audio"), {})
41
+
42
+ summary = {
43
+ "filename": os.path.basename(fmt.get("filename", "")),
44
+ "format": fmt.get("format_long_name") or fmt.get("format_name"),
45
+ "duration_sec": fmt.get("duration"),
46
+ "size_bytes": fmt.get("size"),
47
+ "overall_bitrate_bps": fmt.get("bit_rate"),
48
+ "video": {
49
+ "codec": v.get("codec_name"),
50
+ "profile": v.get("profile"),
51
+ "width": v.get("width"),
52
+ "height": v.get("height"),
53
+ "pix_fmt": v.get("pix_fmt"),
54
+ "frame_rate": v.get("r_frame_rate"),
55
+ "bitrate_bps": v.get("bit_rate"),
56
+ },
57
+ "audio": {
58
+ "codec": a.get("codec_name"),
59
+ "sample_rate": a.get("sample_rate"),
60
+ "channels": a.get("channels"),
61
+ "bitrate_bps": a.get("bit_rate"),
62
+ },
63
+ }
64
+ return json.dumps(summary, indent=2, ensure_ascii=False), video_path
65
+
66
+
67
+ with gr.Blocks(title="OneVision Encoder Codec View") as demo:
68
+ gr.Markdown(
69
+ "# OneVision Encoder Codec View\n"
70
+ "Upload a video to inspect its container / codec metadata via `ffprobe`."
71
+ )
72
+ with gr.Row():
73
+ with gr.Column():
74
+ video_in = gr.Video(label="Input video", sources=["upload"])
75
+ run_btn = gr.Button("Probe", variant="primary")
76
+ with gr.Column():
77
+ video_out = gr.Video(label="Preview")
78
+ info_out = gr.Code(label="Metadata (JSON)", language="json")
79
+ run_btn.click(probe_video, inputs=video_in, outputs=[info_out, video_out])
80
+
81
+
82
+ if __name__ == "__main__":
83
+ demo.launch()
packages.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ ffmpeg