timescodeyt / app.py
saltudio's picture
fix err
e107f19 verified
import gradio as gr
import os, re, tempfile
from typing import List, Tuple
from pydub import AudioSegment
# ---------- Utils ----------
def ms_to_hhmmss(ms: int) -> str:
sec = int(round(ms / 1000.0))
h = sec // 3600
m = (sec % 3600) // 60
s = sec % 60
return f"{h:02d}:{m:02d}:{s:02d}" if h > 0 else f"{m:02d}:{s:02d}"
def clean_title(path: str) -> str:
base = os.path.splitext(os.path.basename(path))[0]
base = re.sub(r"^\s*\d{1,3}[\.\-\)_\s]+", "", base) # hapus โ€œ01. โ€, โ€œ1 - โ€, โ€œ02_โ€ dll
base = re.sub(r"\s{2,}", " ", base).strip()
return base or "Untitled"
def natural_key(name: str):
b = os.path.basename(name)
return [int(t) if t.isdigit() else t.lower() for t in re.split(r"(\d+)", b)]
# ---------- Core ----------
def build_timecodes_from_paths(paths: List[str]) -> Tuple[str, str]:
if not paths:
return "Please upload audio files.", None
# paths dari gr.File(file_count='multiple', type='filepath') -> List[str]
# sort natural agar 01 < 2 < 10
paths = sorted(paths, key=natural_key)
starts, titles, cursor = [], [], 0
skipped = []
for p in paths:
try:
seg = AudioSegment.from_file(p)
starts.append(cursor)
titles.append(clean_title(p))
cursor += len(seg)
except Exception as e:
skipped.append(f"{os.path.basename(p)} ({e})")
if not starts:
return "No readable audio files. Please re-upload.", None
lines = [f"{ms_to_hhmmss(ts)} โ€“ {t}" for ts, t in zip(starts, titles)]
if skipped:
lines.append("\n# Skipped files")
lines += [f"- {msg}" for msg in skipped]
tmpdir = tempfile.mkdtemp()
out_path = os.path.join(tmpdir, "timecodes.txt")
with open(out_path, "w", encoding="utf-8") as f:
f.write("\n".join(lines))
return "\n".join(lines), out_path
# ---------- UI ----------
with gr.Blocks(title="Auto Timecode Generator (Batch Tracks)") as demo:
gr.Markdown(
"## ๐ŸŽถ Auto Timecode Generator (Batch โ†’ YouTube)\n"
"Upload beberapa file audio (MP3/WAV/FLAC/M4A). Aplikasi akan:\n"
"- Urutkan berdasarkan **nama file** (natural sort)\n"
"- Ambil **judul** dari nama file (tanpa nomor & ekstensi)\n"
"- Hitung **timestamp kumulatif** berdasarkan durasi tiap file\n"
"- Menghasilkan output siap **copyโ€“paste** + **download `timecodes.txt`**"
)
files = gr.File(
label="Upload multiple audio files",
file_count="multiple", # <- penting
type="filepath", # <- penting
)
btn = gr.Button("Generate Timecodes", variant="primary")
out = gr.Textbox(label="Timecodes", lines=22)
dl = gr.File(label="Download timecodes.txt")
# Auto-generate begitu selesai upload
files.upload(fn=build_timecodes_from_paths, inputs=[files], outputs=[out, dl])
# Tombol manual juga ada
btn.click(fn=build_timecodes_from_paths, inputs=[files], outputs=[out, dl])
if __name__ == "__main__":
demo.launch()