Spaces:
Running
Running
Commit
·
f55b556
1
Parent(s):
3fd7282
(wip)debug
Browse files- templates/arena.html +62 -53
- tts.py +1 -1
templates/arena.html
CHANGED
|
@@ -26,6 +26,7 @@
|
|
| 26 |
<input type="file" id="voice-file" accept="audio/*">
|
| 27 |
<audio id="voice-preview" controls style="display:none;"></audio>
|
| 28 |
</div>
|
|
|
|
| 29 |
<div class="input-group">
|
| 30 |
<button type="button" class="segmented-btn random-btn" title="Roll random text">
|
| 31 |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
|
|
@@ -45,7 +46,8 @@
|
|
| 45 |
</form>
|
| 46 |
|
| 47 |
<div id="initial-keyboard-hint" class="keyboard-hint">
|
| 48 |
-
Press <kbd>R</kbd> for random text, <kbd>
|
|
|
|
| 49 |
</div>
|
| 50 |
|
| 51 |
<div class="loading-container" style="display: none;">
|
|
@@ -107,7 +109,8 @@
|
|
| 107 |
<button class="next-round-btn">Next Round</button>
|
| 108 |
</div>
|
| 109 |
<div id="playback-keyboard-hint" class="keyboard-hint" style="display: none;">
|
| 110 |
-
Press <kbd>Space</kbd> to play/pause, <kbd>A</kbd>/<kbd>B</kbd> to vote, <kbd>R</kbd> for random text, <kbd>
|
|
|
|
| 111 |
for next random round
|
| 112 |
</div>
|
| 113 |
</div>
|
|
@@ -141,18 +144,13 @@
|
|
| 141 |
|
| 142 |
.random-voice-btn {
|
| 143 |
height: 36px;
|
| 144 |
-
width:
|
| 145 |
-
background-color: white;
|
| 146 |
border: 1px solid var(--border-color);
|
| 147 |
border-radius: var(--radius);
|
| 148 |
margin-right: 10px;
|
| 149 |
flex-shrink: 0;
|
| 150 |
}
|
| 151 |
|
| 152 |
-
.random-voice-btn:hover {
|
| 153 |
-
background-color: var(--light-gray);
|
| 154 |
-
}
|
| 155 |
-
|
| 156 |
.random-voice-btn svg {
|
| 157 |
color: var(--primary-color);
|
| 158 |
}
|
|
@@ -629,51 +627,7 @@
|
|
| 629 |
const voiceFileInput = document.getElementById('voice-file');
|
| 630 |
const voicePreview = document.getElementById('voice-preview');
|
| 631 |
if (randomVoiceBtn && voiceFileInput && voicePreview) {
|
| 632 |
-
randomVoiceBtn.addEventListener('click',
|
| 633 |
-
// 显示加载状态
|
| 634 |
-
randomVoiceBtn.classList.add('loading');
|
| 635 |
-
|
| 636 |
-
// 获取随机参考音色
|
| 637 |
-
fetch('/api/voice/random')
|
| 638 |
-
.then(response => {
|
| 639 |
-
if (!response.ok) {
|
| 640 |
-
throw new Error('获取随机音色失败');
|
| 641 |
-
}
|
| 642 |
-
return response.blob();
|
| 643 |
-
})
|
| 644 |
-
.then(audioBlob => {
|
| 645 |
-
// 创建文件对象,用于合成时提交
|
| 646 |
-
const fileName = 'random_voice_sample.' +
|
| 647 |
-
(audioBlob.type.split('/')[1] || 'mp3');
|
| 648 |
-
|
| 649 |
-
// 创建File对象,用于后续上传
|
| 650 |
-
const audioFile = new File([audioBlob], fileName, {type: audioBlob.type});
|
| 651 |
-
|
| 652 |
-
// 创建一个DataTransfer对象来模拟文件输入
|
| 653 |
-
const dataTransfer = new DataTransfer();
|
| 654 |
-
dataTransfer.items.add(audioFile);
|
| 655 |
-
voiceFileInput.files = dataTransfer.files;
|
| 656 |
-
|
| 657 |
-
// 更新音频预览
|
| 658 |
-
const audioUrl = URL.createObjectURL(audioBlob);
|
| 659 |
-
voicePreview.src = audioUrl;
|
| 660 |
-
voicePreview.style.display = 'inline-block';
|
| 661 |
-
voicePreview.load();
|
| 662 |
-
voicePreview.play();
|
| 663 |
-
|
| 664 |
-
// 触发change事件,确保其他监听器知道文件已更改
|
| 665 |
-
const event = new Event('change', {bubbles: true});
|
| 666 |
-
voiceFileInput.dispatchEvent(event);
|
| 667 |
-
})
|
| 668 |
-
.catch(error => {
|
| 669 |
-
console.error('获取随机音色出错:', error);
|
| 670 |
-
openToast ? openToast("获取随机参考音色失败", "error") : alert("获取随机参考音色失败");
|
| 671 |
-
})
|
| 672 |
-
.finally(() => {
|
| 673 |
-
// 移除加载状态
|
| 674 |
-
randomVoiceBtn.classList.remove('loading');
|
| 675 |
-
});
|
| 676 |
-
});
|
| 677 |
voiceFileInput.addEventListener('change', function () {
|
| 678 |
const file = this.files[0];
|
| 679 |
if (file) {
|
|
@@ -1056,6 +1010,56 @@
|
|
| 1056 |
textInput.focus();
|
| 1057 |
}
|
| 1058 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1059 |
function showListenToastMessage() {
|
| 1060 |
openToast("Please listen to both audio samples before voting", "info");
|
| 1061 |
}
|
|
@@ -1139,6 +1143,11 @@
|
|
| 1139 |
e.preventDefault();
|
| 1140 |
handleRandom();
|
| 1141 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1142 |
} else if (e.key === ' ') {
|
| 1143 |
// Space to play/pause current audio
|
| 1144 |
if (playersContainer.style.display !== 'none') {
|
|
|
|
| 26 |
<input type="file" id="voice-file" accept="audio/*">
|
| 27 |
<audio id="voice-preview" controls style="display:none;"></audio>
|
| 28 |
</div>
|
| 29 |
+
<hr>
|
| 30 |
<div class="input-group">
|
| 31 |
<button type="button" class="segmented-btn random-btn" title="Roll random text">
|
| 32 |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
|
|
|
|
| 46 |
</form>
|
| 47 |
|
| 48 |
<div id="initial-keyboard-hint" class="keyboard-hint">
|
| 49 |
+
Press <kbd>R</kbd> for random text, <kbd>V</kbd> for random reference voice, <kbd>N</kbd> for next random
|
| 50 |
+
round, <kbd>Enter</kbd> to generate
|
| 51 |
</div>
|
| 52 |
|
| 53 |
<div class="loading-container" style="display: none;">
|
|
|
|
| 109 |
<button class="next-round-btn">Next Round</button>
|
| 110 |
</div>
|
| 111 |
<div id="playback-keyboard-hint" class="keyboard-hint" style="display: none;">
|
| 112 |
+
Press <kbd>Space</kbd> to play/pause, <kbd>A</kbd>/<kbd>B</kbd> to vote, <kbd>R</kbd> for random text, <kbd>V</kbd>
|
| 113 |
+
for random reference voice, <kbd>N</kbd>
|
| 114 |
for next random round
|
| 115 |
</div>
|
| 116 |
</div>
|
|
|
|
| 144 |
|
| 145 |
.random-voice-btn {
|
| 146 |
height: 36px;
|
| 147 |
+
width: 48px;
|
|
|
|
| 148 |
border: 1px solid var(--border-color);
|
| 149 |
border-radius: var(--radius);
|
| 150 |
margin-right: 10px;
|
| 151 |
flex-shrink: 0;
|
| 152 |
}
|
| 153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
.random-voice-btn svg {
|
| 155 |
color: var(--primary-color);
|
| 156 |
}
|
|
|
|
| 627 |
const voiceFileInput = document.getElementById('voice-file');
|
| 628 |
const voicePreview = document.getElementById('voice-preview');
|
| 629 |
if (randomVoiceBtn && voiceFileInput && voicePreview) {
|
| 630 |
+
randomVoiceBtn.addEventListener('click', handleRandomVoice);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 631 |
voiceFileInput.addEventListener('change', function () {
|
| 632 |
const file = this.files[0];
|
| 633 |
if (file) {
|
|
|
|
| 1010 |
textInput.focus();
|
| 1011 |
}
|
| 1012 |
|
| 1013 |
+
function handleRandomVoice() {
|
| 1014 |
+
const randomVoiceBtn = document.querySelector('.random-voice-btn');
|
| 1015 |
+
const voiceFileInput = document.getElementById('voice-file');
|
| 1016 |
+
const voicePreview = document.getElementById('voice-preview');
|
| 1017 |
+
|
| 1018 |
+
// 显示加载状态
|
| 1019 |
+
randomVoiceBtn.classList.add('loading');
|
| 1020 |
+
|
| 1021 |
+
// 获取随机参考音色
|
| 1022 |
+
fetch('/api/voice/random')
|
| 1023 |
+
.then(response => {
|
| 1024 |
+
if (!response.ok) {
|
| 1025 |
+
throw new Error('获取随机音色失败');
|
| 1026 |
+
}
|
| 1027 |
+
return response.blob();
|
| 1028 |
+
})
|
| 1029 |
+
.then(audioBlob => {
|
| 1030 |
+
// 创建文件对象,用于合成时提交
|
| 1031 |
+
const fileName = 'random_voice_sample.' +
|
| 1032 |
+
(audioBlob.type.split('/')[1] || 'mp3');
|
| 1033 |
+
|
| 1034 |
+
// 创建File对象,用于后续上传
|
| 1035 |
+
const audioFile = new File([audioBlob], fileName, {type: audioBlob.type});
|
| 1036 |
+
|
| 1037 |
+
// 创建一个DataTransfer对象来模拟文件输入
|
| 1038 |
+
const dataTransfer = new DataTransfer();
|
| 1039 |
+
dataTransfer.items.add(audioFile);
|
| 1040 |
+
voiceFileInput.files = dataTransfer.files;
|
| 1041 |
+
|
| 1042 |
+
// 更新音频预览
|
| 1043 |
+
const audioUrl = URL.createObjectURL(audioBlob);
|
| 1044 |
+
voicePreview.src = audioUrl;
|
| 1045 |
+
voicePreview.style.display = 'inline-block';
|
| 1046 |
+
voicePreview.load();
|
| 1047 |
+
voicePreview.play();
|
| 1048 |
+
|
| 1049 |
+
// 触发change事件,确保其他监听器知道文件已更改
|
| 1050 |
+
const event = new Event('change', {bubbles: true});
|
| 1051 |
+
voiceFileInput.dispatchEvent(event);
|
| 1052 |
+
})
|
| 1053 |
+
.catch(error => {
|
| 1054 |
+
console.error('获取随机音色出错:', error);
|
| 1055 |
+
openToast ? openToast("获取随机参考音色失败", "error") : alert("获取随机参考音色失败");
|
| 1056 |
+
})
|
| 1057 |
+
.finally(() => {
|
| 1058 |
+
// 移除加载状态
|
| 1059 |
+
randomVoiceBtn.classList.remove('loading');
|
| 1060 |
+
});
|
| 1061 |
+
}
|
| 1062 |
+
|
| 1063 |
function showListenToastMessage() {
|
| 1064 |
openToast("Please listen to both audio samples before voting", "info");
|
| 1065 |
}
|
|
|
|
| 1143 |
e.preventDefault();
|
| 1144 |
handleRandom();
|
| 1145 |
}
|
| 1146 |
+
} else if (e.key.toLowerCase() === 'v') {
|
| 1147 |
+
if (!e.ctrlKey && !e.metaKey && !e.altKey) {
|
| 1148 |
+
e.preventDefault();
|
| 1149 |
+
handleRandomVoice();
|
| 1150 |
+
}
|
| 1151 |
} else if (e.key === ' ') {
|
| 1152 |
// Space to play/pause current audio
|
| 1153 |
if (playersContainer.style.display !== 'none') {
|
tts.py
CHANGED
|
@@ -47,7 +47,7 @@ data = {"text": "string", "provider": "string", "model": "string"}
|
|
| 47 |
|
| 48 |
def predict_index_tts(text, reference_audio_path=None):
|
| 49 |
from gradio_client import Client, handle_file
|
| 50 |
-
client = Client("kemuriririn/IndexTTS")
|
| 51 |
if reference_audio_path:
|
| 52 |
prompt = handle_file(reference_audio_path)
|
| 53 |
else:
|
|
|
|
| 47 |
|
| 48 |
def predict_index_tts(text, reference_audio_path=None):
|
| 49 |
from gradio_client import Client, handle_file
|
| 50 |
+
client = Client("kemuriririn/IndexTTS",verbose=True)
|
| 51 |
if reference_audio_path:
|
| 52 |
prompt = handle_file(reference_audio_path)
|
| 53 |
else:
|