Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- app.py +23 -37
- replay.html +58 -0
app.py
CHANGED
@@ -1,46 +1,32 @@
|
|
1 |
import gradio as gr
|
2 |
import os
|
3 |
-
import subprocess
|
4 |
from infer import infer_midi_from_wav
|
5 |
|
6 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
7 |
|
8 |
-
# MIDI
|
9 |
-
def
|
10 |
-
soundfont_path = os.path.join(BASE_DIR, "soundfont.sf2") # SoundFontファイルが必要
|
11 |
-
wav_path = os.path.join(BASE_DIR, "synth_output.wav")
|
12 |
-
|
13 |
-
command = [
|
14 |
-
"fluidsynth",
|
15 |
-
"-ni",
|
16 |
-
soundfont_path,
|
17 |
-
midi_path,
|
18 |
-
"-F",
|
19 |
-
wav_path,
|
20 |
-
"-r",
|
21 |
-
"44100"
|
22 |
-
]
|
23 |
-
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
24 |
-
if result.returncode != 0:
|
25 |
-
raise RuntimeError("fluidsynth conversion failed:\n" + result.stderr.decode())
|
26 |
-
return wav_path
|
27 |
-
|
28 |
-
# 推論関数
|
29 |
-
def transcribe_and_play(audio_path):
|
30 |
midi_path = infer_midi_from_wav(audio_path)
|
31 |
-
|
32 |
-
|
|
|
|
|
33 |
|
34 |
# Gradio インターフェース
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
gr.
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
import os
|
|
|
3 |
from infer import infer_midi_from_wav
|
4 |
|
5 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
6 |
|
7 |
+
# 推論関数(MIDI生成のみ)
|
8 |
+
def transcribe(audio_path):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
midi_path = infer_midi_from_wav(audio_path)
|
10 |
+
return midi_path
|
11 |
+
|
12 |
+
# HTML再生用(replay.htmlを読み込む)
|
13 |
+
replay_html = open(os.path.join(BASE_DIR, "replay.html")).read()
|
14 |
|
15 |
# Gradio インターフェース
|
16 |
+
with gr.Blocks() as demo:
|
17 |
+
gr.Markdown("## 鼻歌からのMIDI変換デモ")
|
18 |
+
gr.Markdown("録音した音声をMIDIに変換し、ブラウザで再生できます。")
|
19 |
+
|
20 |
+
with gr.Row():
|
21 |
+
audio_input = gr.Audio(type="filepath", label="マイク録音")
|
22 |
+
midi_output = gr.File(label="変換されたMIDI")
|
23 |
+
|
24 |
+
run_btn = gr.Button("▶️ 変換")
|
25 |
+
|
26 |
+
# MIDI変換ボタンを押すとMIDIファイルを出力
|
27 |
+
run_btn.click(fn=transcribe, inputs=audio_input, outputs=midi_output)
|
28 |
+
|
29 |
+
# HTMLによるMIDI再生UI
|
30 |
+
gr.HTML(replay_html)
|
31 |
+
|
32 |
+
demo.launch()
|
replay.html
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>MIDI Player</title>
|
5 |
+
</head>
|
6 |
+
<body>
|
7 |
+
<h3>MIDIファイルをブラウザで再生</h3>
|
8 |
+
<input type="file" id="midi-upload" accept=".mid"/>
|
9 |
+
<br/><br/>
|
10 |
+
<button onclick="playMIDI()">▶️ 再生</button>
|
11 |
+
<button onclick="stopMIDI()">⏹ 停止</button>
|
12 |
+
<p id="status"></p>
|
13 |
+
|
14 |
+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/MIDI.min.js"></script>
|
15 |
+
<script>
|
16 |
+
let isLoaded = false;
|
17 |
+
|
18 |
+
MIDI.loadPlugin({
|
19 |
+
soundfontUrl: "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/",
|
20 |
+
instrument: "acoustic_grand_piano",
|
21 |
+
onsuccess: function() {
|
22 |
+
isLoaded = true;
|
23 |
+
document.getElementById("status").innerText = "✅ サウンドフォント読み込み完了";
|
24 |
+
}
|
25 |
+
});
|
26 |
+
|
27 |
+
function playMIDI() {
|
28 |
+
if (!isLoaded) {
|
29 |
+
alert("サウンドフォント読み込み中です。少し待ってから再度お試しください。");
|
30 |
+
return;
|
31 |
+
}
|
32 |
+
|
33 |
+
const fileInput = document.getElementById("midi-upload");
|
34 |
+
const file = fileInput.files[0];
|
35 |
+
|
36 |
+
if (!file) {
|
37 |
+
alert("MIDIファイルを選択してください。");
|
38 |
+
return;
|
39 |
+
}
|
40 |
+
|
41 |
+
const reader = new FileReader();
|
42 |
+
reader.onload = function(e) {
|
43 |
+
const base64data = e.target.result.split(',')[1];
|
44 |
+
MIDI.Player.loadFile("data:audio/midi;base64," + base64data, () => {
|
45 |
+
MIDI.Player.start();
|
46 |
+
document.getElementById("status").innerText = "🎵 再生中...";
|
47 |
+
});
|
48 |
+
};
|
49 |
+
reader.readAsDataURL(file);
|
50 |
+
}
|
51 |
+
|
52 |
+
function stopMIDI() {
|
53 |
+
MIDI.Player.stop();
|
54 |
+
document.getElementById("status").innerText = "⏹ 停止しました";
|
55 |
+
}
|
56 |
+
</script>
|
57 |
+
</body>
|
58 |
+
</html>
|