Spaces:
Sleeping
Sleeping
Create audio_cutter.py
Browse files- audio_cutter.py +75 -0
audio_cutter.py
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# sound_editer.py
|
2 |
+
|
3 |
+
import os
|
4 |
+
import streamlit as st
|
5 |
+
from pydub import AudioSegment
|
6 |
+
from io import BytesIO
|
7 |
+
import tempfile
|
8 |
+
from datetime import timedelta
|
9 |
+
|
10 |
+
# ✅ ffmpeg のパスを指定
|
11 |
+
ffmpeg_bin = r"C:\Users\yamas\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-7.1.1-full_build\bin"
|
12 |
+
os.environ["PATH"] += os.pathsep + ffmpeg_bin
|
13 |
+
AudioSegment.converter = os.path.join(ffmpeg_bin, "ffmpeg.exe")
|
14 |
+
AudioSegment.ffprobe = os.path.join(ffmpeg_bin, "ffprobe.exe")
|
15 |
+
|
16 |
+
# アプリ設定
|
17 |
+
st.set_page_config(page_title="音声カッター", layout="centered")
|
18 |
+
st.title("✂️ 音声ファイルカッター(シンプル&見やすい)")
|
19 |
+
|
20 |
+
uploaded_file = st.file_uploader("音声ファイルを選んでください(mp3, wav, m4a)", type=["mp3", "wav", "m4a"])
|
21 |
+
|
22 |
+
def format_time(seconds: float) -> str:
|
23 |
+
return str(timedelta(seconds=round(seconds)))
|
24 |
+
|
25 |
+
if uploaded_file:
|
26 |
+
st.audio(uploaded_file)
|
27 |
+
|
28 |
+
try:
|
29 |
+
# 一時ファイルに保存
|
30 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".tmp") as tmp:
|
31 |
+
tmp.write(uploaded_file.read())
|
32 |
+
audio = AudioSegment.from_file(tmp.name)
|
33 |
+
|
34 |
+
duration_sec = len(audio) / 1000.0
|
35 |
+
|
36 |
+
if duration_sec < 0.01:
|
37 |
+
st.warning("❗ 音声が短すぎて切り出せません。")
|
38 |
+
st.stop()
|
39 |
+
|
40 |
+
st.subheader("🎚️ 切り出したい範囲を選んでください")
|
41 |
+
start_sec, end_sec = st.slider(
|
42 |
+
f"範囲(全長 {format_time(duration_sec)})",
|
43 |
+
min_value=0.0,
|
44 |
+
max_value=duration_sec,
|
45 |
+
value=(0.0, min(1.0, duration_sec)),
|
46 |
+
step=0.01
|
47 |
+
)
|
48 |
+
|
49 |
+
col1, col2 = st.columns(2)
|
50 |
+
col1.write(f"▶️ 開始時間: `{format_time(start_sec)}`")
|
51 |
+
col2.write(f"⏹️ 終了時間: `{format_time(end_sec)}`")
|
52 |
+
|
53 |
+
if st.button("🎬 切り出して保存"):
|
54 |
+
if start_sec >= end_sec:
|
55 |
+
st.warning("⚠️ 終了時間は開始時間より後にしてください。")
|
56 |
+
else:
|
57 |
+
start_ms = int(start_sec * 1000)
|
58 |
+
end_ms = int(end_sec * 1000)
|
59 |
+
cut_audio = audio[start_ms:end_ms]
|
60 |
+
|
61 |
+
buf = BytesIO()
|
62 |
+
cut_audio.export(buf, format="mp3")
|
63 |
+
buf.seek(0)
|
64 |
+
|
65 |
+
st.success("✅ 切り出し完了!")
|
66 |
+
st.audio(buf, format="audio/mp3")
|
67 |
+
st.download_button(
|
68 |
+
label="💾 ダウンロード(MP3)",
|
69 |
+
data=buf,
|
70 |
+
file_name="cut_audio.mp3",
|
71 |
+
mime="audio/mpeg"
|
72 |
+
)
|
73 |
+
|
74 |
+
except Exception as e:
|
75 |
+
st.error(f"❌ エラーが発生しました:\n\n{e}")
|