audio_cutter / app.py
syamashita's picture
Update app.py
160e8ff verified
# app.py
import streamlit as st
from pydub import AudioSegment
from io import BytesIO
import tempfile
from datetime import timedelta
# ✅ ffmpeg はサーバにインストール済みなので、明示的なパス指定は不要!
# AudioSegment.converter や AudioSegment.ffprobe は書かなくてOK
# アプリ設定
st.set_page_config(page_title="音声カッター", layout="centered")
st.title("✂️ 音声ファイルカッター(シンプル&見やすい)")
uploaded_file = st.file_uploader("音声ファイルを選んでください(mp3, wav, m4a)", type=["mp3", "wav", "m4a"])
def format_time(seconds: float) -> str:
return str(timedelta(seconds=round(seconds)))
if uploaded_file:
st.audio(uploaded_file)
try:
# 一時ファイルに保存
with tempfile.NamedTemporaryFile(delete=False, suffix=".tmp") as tmp:
tmp.write(uploaded_file.read())
audio = AudioSegment.from_file(tmp.name)
duration_sec = len(audio) / 1000.0
if duration_sec < 0.01:
st.warning("❗ 音声が短すぎて切り出せません。")
st.stop()
st.subheader("🎚️ 切り出したい範囲を選んでください")
start_sec, end_sec = st.slider(
f"範囲(全長 {format_time(duration_sec)})",
min_value=0.0,
max_value=duration_sec,
value=(0.0, min(1.0, duration_sec)),
step=0.01
)
col1, col2 = st.columns(2)
col1.write(f"▶️ 開始時間: `{format_time(start_sec)}`")
col2.write(f"⏹️ 終了時間: `{format_time(end_sec)}`")
if st.button("🎬 切り出して保存"):
if start_sec >= end_sec:
st.warning("⚠️ 終了時間は開始時間より後にしてください。")
else:
start_ms = int(start_sec * 1000)
end_ms = int(end_sec * 1000)
cut_audio = audio[start_ms:end_ms]
buf = BytesIO()
cut_audio.export(buf, format="mp3")
buf.seek(0)
st.success("✅ 切り出し完了!")
st.audio(buf, format="audio/mp3")
st.download_button(
label="💾 ダウンロード(MP3)",
data=buf,
file_name="cut_audio.mp3",
mime="audio/mpeg"
)
except Exception as e:
st.error(f"❌ エラーが発生しました:\n\n{e}")