diff --git a/assets/audio/br_003.mp3 b/assets/audio/br_003.mp3 new file mode 100644 index 0000000..6581228 Binary files /dev/null and b/assets/audio/br_003.mp3 differ diff --git a/assets/audio/br_004.mp3 b/assets/audio/br_004.mp3 new file mode 100644 index 0000000..d1acf0b Binary files /dev/null and b/assets/audio/br_004.mp3 differ diff --git a/assets/audio/br_005.mp3 b/assets/audio/br_005.mp3 new file mode 100644 index 0000000..df3fe38 Binary files /dev/null and b/assets/audio/br_005.mp3 differ diff --git a/assets/audio/de_001.mp3 b/assets/audio/de_001.mp3 new file mode 100644 index 0000000..7f41ad2 Binary files /dev/null and b/assets/audio/de_001.mp3 differ diff --git a/assets/audio/de_002.mp3 b/assets/audio/de_002.mp3 new file mode 100644 index 0000000..ed9aa0d Binary files /dev/null and b/assets/audio/de_002.mp3 differ diff --git a/assets/audio/en_au_001.mp3 b/assets/audio/en_au_001.mp3 new file mode 100644 index 0000000..1679af3 Binary files /dev/null and b/assets/audio/en_au_001.mp3 differ diff --git a/assets/audio/en_au_002.mp3 b/assets/audio/en_au_002.mp3 new file mode 100644 index 0000000..18018d6 Binary files /dev/null and b/assets/audio/en_au_002.mp3 differ diff --git a/assets/audio/en_female_betty.mp3 b/assets/audio/en_female_betty.mp3 new file mode 100644 index 0000000..abe2677 Binary files /dev/null and b/assets/audio/en_female_betty.mp3 differ diff --git a/assets/audio/en_female_emotional.mp3 b/assets/audio/en_female_emotional.mp3 new file mode 100644 index 0000000..ed30eea Binary files /dev/null and b/assets/audio/en_female_emotional.mp3 differ diff --git a/assets/audio/en_female_f08_salut_damour.mp3 b/assets/audio/en_female_f08_salut_damour.mp3 new file mode 100644 index 0000000..f007045 Binary files /dev/null and b/assets/audio/en_female_f08_salut_damour.mp3 differ diff --git a/assets/audio/en_female_f08_twinkle.mp3 b/assets/audio/en_female_f08_twinkle.mp3 new file mode 100644 index 0000000..47fb768 Binary files /dev/null and b/assets/audio/en_female_f08_twinkle.mp3 differ diff --git a/assets/audio/en_female_f08_warmy_breeze.mp3 b/assets/audio/en_female_f08_warmy_breeze.mp3 new file mode 100644 index 0000000..c8d0576 Binary files /dev/null and b/assets/audio/en_female_f08_warmy_breeze.mp3 differ diff --git a/assets/audio/en_female_grandma.mp3 b/assets/audio/en_female_grandma.mp3 new file mode 100644 index 0000000..8490bd0 Binary files /dev/null and b/assets/audio/en_female_grandma.mp3 differ diff --git a/assets/audio/en_female_ht_f08_glorious.mp3 b/assets/audio/en_female_ht_f08_glorious.mp3 new file mode 100644 index 0000000..b1edd23 Binary files /dev/null and b/assets/audio/en_female_ht_f08_glorious.mp3 differ diff --git a/assets/audio/en_female_ht_f08_halloween.mp3 b/assets/audio/en_female_ht_f08_halloween.mp3 new file mode 100644 index 0000000..0275509 Binary files /dev/null and b/assets/audio/en_female_ht_f08_halloween.mp3 differ diff --git a/assets/audio/en_female_ht_f08_newyear.mp3 b/assets/audio/en_female_ht_f08_newyear.mp3 new file mode 100644 index 0000000..f962ecb Binary files /dev/null and b/assets/audio/en_female_ht_f08_newyear.mp3 differ diff --git a/assets/audio/en_female_ht_f08_wonderful_world.mp3 b/assets/audio/en_female_ht_f08_wonderful_world.mp3 new file mode 100644 index 0000000..207ec7f Binary files /dev/null and b/assets/audio/en_female_ht_f08_wonderful_world.mp3 differ diff --git a/assets/audio/en_female_madam_leota.mp3 b/assets/audio/en_female_madam_leota.mp3 new file mode 100644 index 0000000..4c4c0fe Binary files /dev/null and b/assets/audio/en_female_madam_leota.mp3 differ diff --git a/assets/audio/en_female_makeup.mp3 b/assets/audio/en_female_makeup.mp3 new file mode 100644 index 0000000..8affb11 Binary files /dev/null and b/assets/audio/en_female_makeup.mp3 differ diff --git a/assets/audio/en_female_pansino.mp3 b/assets/audio/en_female_pansino.mp3 new file mode 100644 index 0000000..0b0bd25 Binary files /dev/null and b/assets/audio/en_female_pansino.mp3 differ diff --git a/assets/audio/en_female_richgirl.mp3 b/assets/audio/en_female_richgirl.mp3 new file mode 100644 index 0000000..128f6a3 Binary files /dev/null and b/assets/audio/en_female_richgirl.mp3 differ diff --git a/assets/audio/en_female_samc.mp3 b/assets/audio/en_female_samc.mp3 new file mode 100644 index 0000000..d83a861 Binary files /dev/null and b/assets/audio/en_female_samc.mp3 differ diff --git a/assets/audio/en_female_shenna.mp3 b/assets/audio/en_female_shenna.mp3 new file mode 100644 index 0000000..1364d56 Binary files /dev/null and b/assets/audio/en_female_shenna.mp3 differ diff --git a/assets/audio/en_male_cody.mp3 b/assets/audio/en_male_cody.mp3 new file mode 100644 index 0000000..c94de53 Binary files /dev/null and b/assets/audio/en_male_cody.mp3 differ diff --git a/assets/audio/en_male_cupid.mp3 b/assets/audio/en_male_cupid.mp3 new file mode 100644 index 0000000..0f3f0ee Binary files /dev/null and b/assets/audio/en_male_cupid.mp3 differ diff --git a/assets/audio/en_male_deadpool.mp3 b/assets/audio/en_male_deadpool.mp3 new file mode 100644 index 0000000..ebdc09d Binary files /dev/null and b/assets/audio/en_male_deadpool.mp3 differ diff --git a/assets/audio/en_male_funny.mp3 b/assets/audio/en_male_funny.mp3 new file mode 100644 index 0000000..aabf850 Binary files /dev/null and b/assets/audio/en_male_funny.mp3 differ diff --git a/assets/audio/en_male_ghosthost.mp3 b/assets/audio/en_male_ghosthost.mp3 new file mode 100644 index 0000000..983cdfc Binary files /dev/null and b/assets/audio/en_male_ghosthost.mp3 differ diff --git a/assets/audio/en_male_grinch.mp3 b/assets/audio/en_male_grinch.mp3 new file mode 100644 index 0000000..6d69ee5 Binary files /dev/null and b/assets/audio/en_male_grinch.mp3 differ diff --git a/assets/audio/en_male_jarvis.mp3 b/assets/audio/en_male_jarvis.mp3 new file mode 100644 index 0000000..ef70450 Binary files /dev/null and b/assets/audio/en_male_jarvis.mp3 differ diff --git a/assets/audio/en_male_m03_classical.mp3 b/assets/audio/en_male_m03_classical.mp3 new file mode 100644 index 0000000..d58adae Binary files /dev/null and b/assets/audio/en_male_m03_classical.mp3 differ diff --git a/assets/audio/en_male_m03_lobby.mp3 b/assets/audio/en_male_m03_lobby.mp3 new file mode 100644 index 0000000..8b3c204 Binary files /dev/null and b/assets/audio/en_male_m03_lobby.mp3 differ diff --git a/assets/audio/en_male_m03_sunshine_soon.mp3 b/assets/audio/en_male_m03_sunshine_soon.mp3 new file mode 100644 index 0000000..e19e97f Binary files /dev/null and b/assets/audio/en_male_m03_sunshine_soon.mp3 differ diff --git a/assets/audio/en_male_m2_xhxs_m03_christmas.mp3 b/assets/audio/en_male_m2_xhxs_m03_christmas.mp3 new file mode 100644 index 0000000..a503de7 Binary files /dev/null and b/assets/audio/en_male_m2_xhxs_m03_christmas.mp3 differ diff --git a/assets/audio/en_male_m2_xhxs_m03_silly.mp3 b/assets/audio/en_male_m2_xhxs_m03_silly.mp3 new file mode 100644 index 0000000..4951520 Binary files /dev/null and b/assets/audio/en_male_m2_xhxs_m03_silly.mp3 differ diff --git a/assets/audio/en_male_narration.mp3 b/assets/audio/en_male_narration.mp3 new file mode 100644 index 0000000..ba6f3a0 Binary files /dev/null and b/assets/audio/en_male_narration.mp3 differ diff --git a/assets/audio/en_male_pirate.mp3 b/assets/audio/en_male_pirate.mp3 new file mode 100644 index 0000000..7668797 Binary files /dev/null and b/assets/audio/en_male_pirate.mp3 differ diff --git a/assets/audio/en_male_santa.mp3 b/assets/audio/en_male_santa.mp3 new file mode 100644 index 0000000..10889fd Binary files /dev/null and b/assets/audio/en_male_santa.mp3 differ diff --git a/assets/audio/en_male_santa_effect.mp3 b/assets/audio/en_male_santa_effect.mp3 new file mode 100644 index 0000000..5a24c6a Binary files /dev/null and b/assets/audio/en_male_santa_effect.mp3 differ diff --git a/assets/audio/en_male_santa_narration.mp3 b/assets/audio/en_male_santa_narration.mp3 new file mode 100644 index 0000000..dbfa9f3 Binary files /dev/null and b/assets/audio/en_male_santa_narration.mp3 differ diff --git a/assets/audio/en_male_sing_deep_jingle.mp3 b/assets/audio/en_male_sing_deep_jingle.mp3 new file mode 100644 index 0000000..710b27d Binary files /dev/null and b/assets/audio/en_male_sing_deep_jingle.mp3 differ diff --git a/assets/audio/en_male_sing_funny_it_goes_up.mp3 b/assets/audio/en_male_sing_funny_it_goes_up.mp3 new file mode 100644 index 0000000..d73ecca Binary files /dev/null and b/assets/audio/en_male_sing_funny_it_goes_up.mp3 differ diff --git a/assets/audio/en_male_sing_funny_thanksgiving.mp3 b/assets/audio/en_male_sing_funny_thanksgiving.mp3 new file mode 100644 index 0000000..8a2b68e Binary files /dev/null and b/assets/audio/en_male_sing_funny_thanksgiving.mp3 differ diff --git a/assets/audio/en_male_trevor.mp3 b/assets/audio/en_male_trevor.mp3 new file mode 100644 index 0000000..67c9d40 Binary files /dev/null and b/assets/audio/en_male_trevor.mp3 differ diff --git a/assets/audio/en_male_ukbutler.mp3 b/assets/audio/en_male_ukbutler.mp3 new file mode 100644 index 0000000..b0a938d Binary files /dev/null and b/assets/audio/en_male_ukbutler.mp3 differ diff --git a/assets/audio/en_male_ukneighbor.mp3 b/assets/audio/en_male_ukneighbor.mp3 new file mode 100644 index 0000000..05a2db5 Binary files /dev/null and b/assets/audio/en_male_ukneighbor.mp3 differ diff --git a/assets/audio/en_male_wizard.mp3 b/assets/audio/en_male_wizard.mp3 new file mode 100644 index 0000000..4b622f6 Binary files /dev/null and b/assets/audio/en_male_wizard.mp3 differ diff --git a/assets/audio/en_uk_001.mp3 b/assets/audio/en_uk_001.mp3 new file mode 100644 index 0000000..61f70a3 Binary files /dev/null and b/assets/audio/en_uk_001.mp3 differ diff --git a/assets/audio/en_uk_003.mp3 b/assets/audio/en_uk_003.mp3 new file mode 100644 index 0000000..e69c5ff Binary files /dev/null and b/assets/audio/en_uk_003.mp3 differ diff --git a/assets/audio/en_us_002.mp3 b/assets/audio/en_us_002.mp3 new file mode 100644 index 0000000..6daefa5 Binary files /dev/null and b/assets/audio/en_us_002.mp3 differ diff --git a/assets/audio/en_us_006.mp3 b/assets/audio/en_us_006.mp3 new file mode 100644 index 0000000..8002cc4 Binary files /dev/null and b/assets/audio/en_us_006.mp3 differ diff --git a/assets/audio/en_us_007.mp3 b/assets/audio/en_us_007.mp3 new file mode 100644 index 0000000..d944b0d Binary files /dev/null and b/assets/audio/en_us_007.mp3 differ diff --git a/assets/audio/en_us_009.mp3 b/assets/audio/en_us_009.mp3 new file mode 100644 index 0000000..a77e7be Binary files /dev/null and b/assets/audio/en_us_009.mp3 differ diff --git a/assets/audio/en_us_010.mp3 b/assets/audio/en_us_010.mp3 new file mode 100644 index 0000000..6707841 Binary files /dev/null and b/assets/audio/en_us_010.mp3 differ diff --git a/assets/audio/en_us_c3po.mp3 b/assets/audio/en_us_c3po.mp3 new file mode 100644 index 0000000..52834d4 Binary files /dev/null and b/assets/audio/en_us_c3po.mp3 differ diff --git a/assets/audio/en_us_chewbacca.mp3 b/assets/audio/en_us_chewbacca.mp3 new file mode 100644 index 0000000..bcd0a6b Binary files /dev/null and b/assets/audio/en_us_chewbacca.mp3 differ diff --git a/assets/audio/en_us_ghostface.mp3 b/assets/audio/en_us_ghostface.mp3 new file mode 100644 index 0000000..4a070d8 Binary files /dev/null and b/assets/audio/en_us_ghostface.mp3 differ diff --git a/assets/audio/en_us_rocket.mp3 b/assets/audio/en_us_rocket.mp3 new file mode 100644 index 0000000..77a19ca Binary files /dev/null and b/assets/audio/en_us_rocket.mp3 differ diff --git a/assets/audio/en_us_stitch.mp3 b/assets/audio/en_us_stitch.mp3 new file mode 100644 index 0000000..e373ea4 Binary files /dev/null and b/assets/audio/en_us_stitch.mp3 differ diff --git a/assets/audio/en_us_stormtrooper.mp3 b/assets/audio/en_us_stormtrooper.mp3 new file mode 100644 index 0000000..cd65cba Binary files /dev/null and b/assets/audio/en_us_stormtrooper.mp3 differ diff --git a/assets/audio/es_002.mp3 b/assets/audio/es_002.mp3 new file mode 100644 index 0000000..58120eb Binary files /dev/null and b/assets/audio/es_002.mp3 differ diff --git a/assets/audio/es_female_f6.mp3 b/assets/audio/es_female_f6.mp3 new file mode 100644 index 0000000..563fb07 Binary files /dev/null and b/assets/audio/es_female_f6.mp3 differ diff --git a/assets/audio/es_female_fp1.mp3 b/assets/audio/es_female_fp1.mp3 new file mode 100644 index 0000000..05f3f15 Binary files /dev/null and b/assets/audio/es_female_fp1.mp3 differ diff --git a/assets/audio/es_male_m3.mp3 b/assets/audio/es_male_m3.mp3 new file mode 100644 index 0000000..fccf1cd Binary files /dev/null and b/assets/audio/es_male_m3.mp3 differ diff --git a/assets/audio/es_mx_002.mp3 b/assets/audio/es_mx_002.mp3 new file mode 100644 index 0000000..5030be0 Binary files /dev/null and b/assets/audio/es_mx_002.mp3 differ diff --git a/assets/audio/es_mx_female_supermom.mp3 b/assets/audio/es_mx_female_supermom.mp3 new file mode 100644 index 0000000..1e413d1 Binary files /dev/null and b/assets/audio/es_mx_female_supermom.mp3 differ diff --git a/assets/audio/es_mx_male_transformer.mp3 b/assets/audio/es_mx_male_transformer.mp3 new file mode 100644 index 0000000..e69de29 diff --git a/assets/audio/fr_001.mp3 b/assets/audio/fr_001.mp3 new file mode 100644 index 0000000..d72ea36 Binary files /dev/null and b/assets/audio/fr_001.mp3 differ diff --git a/assets/audio/fr_002.mp3 b/assets/audio/fr_002.mp3 new file mode 100644 index 0000000..fe40092 Binary files /dev/null and b/assets/audio/fr_002.mp3 differ diff --git a/assets/audio/id_female_icha.mp3 b/assets/audio/id_female_icha.mp3 new file mode 100644 index 0000000..eb7ee91 Binary files /dev/null and b/assets/audio/id_female_icha.mp3 differ diff --git a/assets/audio/id_female_noor.mp3 b/assets/audio/id_female_noor.mp3 new file mode 100644 index 0000000..5290816 Binary files /dev/null and b/assets/audio/id_female_noor.mp3 differ diff --git a/assets/audio/id_male_darma.mp3 b/assets/audio/id_male_darma.mp3 new file mode 100644 index 0000000..fbd97c1 Binary files /dev/null and b/assets/audio/id_male_darma.mp3 differ diff --git a/assets/audio/id_male_putra.mp3 b/assets/audio/id_male_putra.mp3 new file mode 100644 index 0000000..3fd8c84 Binary files /dev/null and b/assets/audio/id_male_putra.mp3 differ diff --git a/assets/audio/it_male_m18.mp3 b/assets/audio/it_male_m18.mp3 new file mode 100644 index 0000000..55928be Binary files /dev/null and b/assets/audio/it_male_m18.mp3 differ diff --git a/assets/audio/jp_001.mp3 b/assets/audio/jp_001.mp3 new file mode 100644 index 0000000..c4e77b0 Binary files /dev/null and b/assets/audio/jp_001.mp3 differ diff --git a/assets/audio/jp_003.mp3 b/assets/audio/jp_003.mp3 new file mode 100644 index 0000000..81393b2 Binary files /dev/null and b/assets/audio/jp_003.mp3 differ diff --git a/assets/audio/jp_005.mp3 b/assets/audio/jp_005.mp3 new file mode 100644 index 0000000..6c0ddf6 Binary files /dev/null and b/assets/audio/jp_005.mp3 differ diff --git a/assets/audio/jp_006.mp3 b/assets/audio/jp_006.mp3 new file mode 100644 index 0000000..08e5dfe Binary files /dev/null and b/assets/audio/jp_006.mp3 differ diff --git a/assets/audio/jp_female_machikoriiita.mp3 b/assets/audio/jp_female_machikoriiita.mp3 new file mode 100644 index 0000000..7cacc87 Binary files /dev/null and b/assets/audio/jp_female_machikoriiita.mp3 differ diff --git a/assets/audio/jp_female_rei.mp3 b/assets/audio/jp_female_rei.mp3 new file mode 100644 index 0000000..6705201 Binary files /dev/null and b/assets/audio/jp_female_rei.mp3 differ diff --git a/assets/audio/jp_female_yagishaki.mp3 b/assets/audio/jp_female_yagishaki.mp3 new file mode 100644 index 0000000..b3dc46d Binary files /dev/null and b/assets/audio/jp_female_yagishaki.mp3 differ diff --git a/assets/audio/jp_male_hikakin.mp3 b/assets/audio/jp_male_hikakin.mp3 new file mode 100644 index 0000000..dea2dae Binary files /dev/null and b/assets/audio/jp_male_hikakin.mp3 differ diff --git a/assets/audio/jp_male_matsudake.mp3 b/assets/audio/jp_male_matsudake.mp3 new file mode 100644 index 0000000..46eca0f Binary files /dev/null and b/assets/audio/jp_male_matsudake.mp3 differ diff --git a/assets/audio/jp_male_matsuo.mp3 b/assets/audio/jp_male_matsuo.mp3 new file mode 100644 index 0000000..0e7d1b3 Binary files /dev/null and b/assets/audio/jp_male_matsuo.mp3 differ diff --git a/assets/audio/jp_male_osada.mp3 b/assets/audio/jp_male_osada.mp3 new file mode 100644 index 0000000..34935c7 Binary files /dev/null and b/assets/audio/jp_male_osada.mp3 differ diff --git a/assets/audio/jp_male_shuichiro.mp3 b/assets/audio/jp_male_shuichiro.mp3 new file mode 100644 index 0000000..14cd124 Binary files /dev/null and b/assets/audio/jp_male_shuichiro.mp3 differ diff --git a/assets/audio/kr_002.mp3 b/assets/audio/kr_002.mp3 new file mode 100644 index 0000000..3646d7a Binary files /dev/null and b/assets/audio/kr_002.mp3 differ diff --git a/assets/audio/kr_003.mp3 b/assets/audio/kr_003.mp3 new file mode 100644 index 0000000..3eb6e2e Binary files /dev/null and b/assets/audio/kr_003.mp3 differ diff --git a/assets/audio/kr_004.mp3 b/assets/audio/kr_004.mp3 new file mode 100644 index 0000000..c2d03d8 Binary files /dev/null and b/assets/audio/kr_004.mp3 differ diff --git a/assets/audio/pt_female_laizza.mp3 b/assets/audio/pt_female_laizza.mp3 new file mode 100644 index 0000000..416f89d Binary files /dev/null and b/assets/audio/pt_female_laizza.mp3 differ diff --git a/assets/audio/pt_female_lhays.mp3 b/assets/audio/pt_female_lhays.mp3 new file mode 100644 index 0000000..1c6aeb2 Binary files /dev/null and b/assets/audio/pt_female_lhays.mp3 differ diff --git a/assets/audio/pt_male_transformer.mp3 b/assets/audio/pt_male_transformer.mp3 new file mode 100644 index 0000000..e69de29 diff --git a/assets/control.html b/assets/control.html index ada5424..2a91818 100644 --- a/assets/control.html +++ b/assets/control.html @@ -106,16 +106,42 @@ class="provider-voice-settings" style="display: none" > - - - - - +
+ + + +
+
+
+ Selected Voices: 0 +
+ +
+ +
+ + + + + + + + + + + + + +
LanguageVoiceGenderSample
+
diff --git a/assets/css/control.css b/assets/css/control.css index c1e98b7..fb39fb3 100644 --- a/assets/css/control.css +++ b/assets/css/control.css @@ -833,4 +833,134 @@ button:not(:disabled):hover { /* Provider-specific styles */ .provider-voice-settings:not(:first-child) { margin-top: var(--spacing-lg); +} + +/* Voice table styles */ +.voice-filter { + display: flex; + gap: var(--spacing-md); + margin-bottom: var(--spacing-lg); +} + +.tts-input { + flex: 2; + padding: var(--spacing-md) var(--spacing-lg); + border-radius: var(--border-radius-md); + border: 1px solid var(--border-color); + font-size: var(--font-sm); +} + +.voice-table-container { + max-height: 400px; + overflow-y: auto; + border: 1px solid var(--border-color); + border-radius: var(--border-radius-md); +} + +.voice-table { + width: 100%; + border-collapse: collapse; +} + +.voice-table th, +.voice-table td { + padding: var(--spacing-md); + text-align: left; + border-bottom: 1px solid var(--border-color); +} + +.voice-table th { + background: var(--color-secondary); + position: sticky; + top: 0; + z-index: 1; +} + +.voice-table tr:hover { + background: var(--color-secondary); +} + +.voice-table .play-sample { + background: none; + border: none; + color: var(--color-primary); + cursor: pointer; + padding: var(--spacing-sm); +} + +.voice-table .play-sample:hover { + color: var(--color-primary-dark); +} + +/* Style the audio player */ +.voice-sample { + height: 30px; + width: 150px; +} + +/* Make the sample column wide enough */ +.voice-table td:last-child { + min-width: 160px; +} + +.voice-filter .tts-select { + flex: 1; +} + +.voice-counter { + margin-bottom: var(--spacing-md); + font-size: var(--font-sm); + color: var(--text-secondary); + font-weight: 500; + display: flex; + justify-content: space-between; + align-items: center; +} + +.voice-counter span { + color: var(--color-primary); + font-weight: 600; +} + +.clear-voices-btn { + border: none; + background: none; + color: var(--color-danger); + font-size: var(--font-xs); + cursor: pointer; + padding: var(--spacing-xs) var(--spacing-sm); + border-radius: var(--border-radius-sm); + transition: var(--transition-default); +} + +.clear-voices-btn:hover { + background: var(--color-danger); + color: white; +} + +.voice-table tr:hover { + background: var(--color-secondary); +} + +.voice-row { + cursor: pointer; +} + +.voice-row .sample-cell { + cursor: default; +} + +/* Prevent text selection when clicking rows */ +.voice-row td:not(.sample-cell) { + user-select: none; +} + +/* Make all cells except sample cell clickable */ +.voice-row td:not(.sample-cell) { + cursor: pointer; + user-select: none; +} + +.voice-row .sample-cell { + cursor: default; } \ No newline at end of file diff --git a/assets/data/tiktok_voice_ids.csv b/assets/data/tiktok_voice_ids.csv index 3adf0a3..12342c2 100644 --- a/assets/data/tiktok_voice_ids.csv +++ b/assets/data/tiktok_voice_ids.csv @@ -1,94 +1,93 @@ -lang_label,voice_name,voice_id -English,Narrator (Chris),en_uk_001 -English,UK Male 2,en_uk_003 -English,Peaceful,en_female_emotional -English,Metro (Eddie),en_au_001 -English,Smooth (Alex),en_au_002 -English,Jessie,en_us_002 -English,Joey,en_us_006 -English,Professor,en_us_007 -English,Scientist,en_us_009 -English,Confidence,en_us_010 -English,Empathetic,en_female_samc -English,Serious,en_male_cody -English,Story Teller,en_male_narration -English,Wacky,en_male_funny -English,Alfred,en_male_jarvis -English,Author,en_male_santa_narration -English,Bae,en_female_betty -English,Beauty Guru,en_female_makeup -English,Bestie,en_female_richgirl -English,Cupid,en_male_cupid -English,Debutante,en_female_shenna -English,Ghost Host,en_male_ghosthost -English,Grandma,en_female_grandma -English,Lord Cringe,en_male_ukneighbor -English,Magician,en_male_wizard -English,Marty,en_male_trevor -English,Mr. GoodGuy (Deadpool),en_male_deadpool -English,Mr. Meticulous,en_male_ukbutler -English,Optimus Prime,en_male_petercullen -English,Pirate,en_male_pirate -English,Santa,en_male_santa -English,Santa (w/ effect),en_male_santa_effect -English,Varsity,en_female_pansino -English,Trickster (Grinch),en_male_grinch -English,Ghostface (Scream),en_us_ghostface -English,Chewbacca (Star Wars),en_us_chewbacca -English,C-3PO (Star Wars),en_us_c3po -English,Stormtrooper (Star Wars),en_us_stormtrooper -English,Stitch (Lilo & Stitch),en_us_stitch -English,Rocket (Guardians of the Galaxy),en_us_rocket -English,Madame Leota (Haunted Mansion),en_female_madam_leota -English,Song: Caroler,en_male_sing_deep_jingle -English,Song: Classic Electric,en_male_m03_classical -English,Song: Cottagecore (Salut d'Amour),en_female_f08_salut_damour -English,Song: Cozy,en_male_m2_xhxs_m03_christmas -English,Song: Open Mic (Warmy Breeze),en_female_f08_warmy_breeze -English,Song: Opera (Halloween),en_female_ht_f08_halloween -English,Song: Euphoric (Glorious),en_female_ht_f08_glorious -English,Song: Hypetrain (It Goes Up),en_male_sing_funny_it_goes_up -English,Song: Jingle (Lobby),en_male_m03_lobby -English,Song: Melodrama (Wonderful World),en_female_ht_f08_wonderful_world -English,Song: NYE 2023,en_female_ht_f08_newyear -English,Song: Thanksgiving,en_male_sing_funny_thanksgiving -English,Song: Toon Beat (Sunshine Soon),en_male_m03_sunshine_soon -English,Song: Pop Lullaby,en_female_f08_twinkle -English,Song: Quirky Time,en_male_m2_xhxs_m03_silly -French,French Male 1,fr_001 -French,French Male 2,fr_002 -German,German Female,de_001 -German,German Male,de_002 -Indonesian,Darma,id_male_darma -Indonesian,Icha,id_female_icha -Indonesian,Noor,id_female_noor -Indonesian,Putra,id_male_putra -Italian,Italian Male,it_male_m18 -Japanese,Miho,jp_001 -Japanese,Keiko,jp_003 -Japanese,Sakura,jp_005 -Japanese,Naoki,jp_006 -Japanese,Morisuke,jp_male_osada -Japanese,Matsuo,jp_male_matsuo -Japanese,Machikoriiita,jp_female_machikoriiita -Japanese,Matsudake,jp_male_matsudake -Japanese,Shuichiro,jp_male_shuichiro -Japanese,Maruyama Rei,jp_female_rei -Japanese,Hikakin,jp_male_hikakin -Japanese,Yagi Saki,jp_female_yagishaki -Korean,Korean Male 1,kr_002 -Korean,Korean Male 2,kr_004 -Korean,Korean Female,kr_003 -Portuguese,Julia,br_003 -Portuguese,Ana,br_004 -Portuguese,Lucas,br_005 -Portuguese,Lhays Macedo,pt_female_lhays -Portuguese,Laizza,pt_female_laizza -Portuguese,Optimus Prime (Portuguese),pt_male_transformer -Spanish,Spanish Male,es_002 -Spanish,Julio,es_male_m3 -Spanish,Alejandra,es_female_f6 -Spanish,Mariana,es_female_fp1 -Spanish,Álex (Warm),es_mx_002 -Spanish,Optimus Prime (Mexican),es_mx_male_transformer -Spanish,Super Mamá,es_mx_female_supermom +lang_label,voice_name,voice_gender,voice_id,sample_sentence,sample_voice +English,Narrator (Chris),neutral,en_uk_001,This is an example sentence in English.,/audio/en_uk_001.mp3 +English,UK Male 2,male,en_uk_003,This is an example sentence in English.,/audio/en_uk_003.mp3 +English,Peaceful,female,en_female_emotional,This is an example sentence in English.,/audio/en_female_emotional.mp3 +English,Metro (Eddie),neutral,en_au_001,This is an example sentence in English.,/audio/en_au_001.mp3 +English,Smooth (Alex),neutral,en_au_002,This is an example sentence in English.,/audio/en_au_002.mp3 +English,Jessie,neutral,en_us_002,This is an example sentence in English.,/audio/en_us_002.mp3 +English,Joey,neutral,en_us_006,This is an example sentence in English.,/audio/en_us_006.mp3 +English,Professor,neutral,en_us_007,This is an example sentence in English.,/audio/en_us_007.mp3 +English,Scientist,neutral,en_us_009,This is an example sentence in English.,/audio/en_us_009.mp3 +English,Confidence,neutral,en_us_010,This is an example sentence in English.,/audio/en_us_010.mp3 +English,Empathetic,female,en_female_samc,This is an example sentence in English.,/audio/en_female_samc.mp3 +English,Serious,male,en_male_cody,This is an example sentence in English.,/audio/en_male_cody.mp3 +English,Story Teller,male,en_male_narration,This is an example sentence in English.,/audio/en_male_narration.mp3 +English,Wacky,male,en_male_funny,This is an example sentence in English.,/audio/en_male_funny.mp3 +English,Alfred,male,en_male_jarvis,This is an example sentence in English.,/audio/en_male_jarvis.mp3 +English,Author,male,en_male_santa_narration,This is an example sentence in English.,/audio/en_male_santa_narration.mp3 +English,Bae,female,en_female_betty,This is an example sentence in English.,/audio/en_female_betty.mp3 +English,Beauty Guru,female,en_female_makeup,This is an example sentence in English.,/audio/en_female_makeup.mp3 +English,Bestie,female,en_female_richgirl,This is an example sentence in English.,/audio/en_female_richgirl.mp3 +English,Cupid,male,en_male_cupid,This is an example sentence in English.,/audio/en_male_cupid.mp3 +English,Debutante,female,en_female_shenna,This is an example sentence in English.,/audio/en_female_shenna.mp3 +English,Ghost Host,male,en_male_ghosthost,This is an example sentence in English.,/audio/en_male_ghosthost.mp3 +English,Grandma,female,en_female_grandma,This is an example sentence in English.,/audio/en_female_grandma.mp3 +English,Lord Cringe,male,en_male_ukneighbor,This is an example sentence in English.,/audio/en_male_ukneighbor.mp3 +English,Magician,male,en_male_wizard,This is an example sentence in English.,/audio/en_male_wizard.mp3 +English,Marty,male,en_male_trevor,This is an example sentence in English.,/audio/en_male_trevor.mp3 +English,Mr. GoodGuy (Deadpool),male,en_male_deadpool,This is an example sentence in English.,/audio/en_male_deadpool.mp3 +English,Mr. Meticulous,male,en_male_ukbutler,This is an example sentence in English.,/audio/en_male_ukbutler.mp3 +English,Pirate,male,en_male_pirate,This is an example sentence in English.,/audio/en_male_pirate.mp3 +English,Santa,male,en_male_santa,This is an example sentence in English.,/audio/en_male_santa.mp3 +English,Santa (w/ effect),male,en_male_santa_effect,This is an example sentence in English.,/audio/en_male_santa_effect.mp3 +English,Varsity,female,en_female_pansino,This is an example sentence in English.,/audio/en_female_pansino.mp3 +English,Trickster (Grinch),male,en_male_grinch,This is an example sentence in English.,/audio/en_male_grinch.mp3 +English,Ghostface (Scream),neutral,en_us_ghostface,This is an example sentence in English.,/audio/en_us_ghostface.mp3 +English,Chewbacca (Star Wars),neutral,en_us_chewbacca,This is an example sentence in English.,/audio/en_us_chewbacca.mp3 +English,C-3PO (Star Wars),neutral,en_us_c3po,This is an example sentence in English.,/audio/en_us_c3po.mp3 +English,Stormtrooper (Star Wars),neutral,en_us_stormtrooper,This is an example sentence in English.,/audio/en_us_stormtrooper.mp3 +English,Stitch (Lilo & Stitch),neutral,en_us_stitch,This is an example sentence in English.,/audio/en_us_stitch.mp3 +English,Rocket (Guardians of the Galaxy),neutral,en_us_rocket,This is an example sentence in English.,/audio/en_us_rocket.mp3 +English,Madame Leota (Haunted Mansion),female,en_female_madam_leota,This is an example sentence in English.,/audio/en_female_madam_leota.mp3 +Song,Song: Caroler,male,en_male_sing_deep_jingle,This is an example sentence in English.,/audio/en_male_sing_deep_jingle.mp3 +Song,Song: Classic Electric,male,en_male_m03_classical,This is an example sentence in English.,/audio/en_male_m03_classical.mp3 +Song,Song: Cottagecore (Salut d'Amour),female,en_female_f08_salut_damour,This is an example sentence in English.,/audio/en_female_f08_salut_damour.mp3 +Song,Song: Cozy,male,en_male_m2_xhxs_m03_christmas,This is an example sentence in English.,/audio/en_male_m2_xhxs_m03_christmas.mp3 +Song,Song: Open Mic (Warmy Breeze),female,en_female_f08_warmy_breeze,This is an example sentence in English.,/audio/en_female_f08_warmy_breeze.mp3 +Song,Song: Opera (Halloween),female,en_female_ht_f08_halloween,This is an example sentence in English.,/audio/en_female_ht_f08_halloween.mp3 +Song,Song: Euphoric (Glorious),female,en_female_ht_f08_glorious,This is an example sentence in English.,/audio/en_female_ht_f08_glorious.mp3 +Song,Song: Hypetrain (It Goes Up),male,en_male_sing_funny_it_goes_up,This is an example sentence in English.,/audio/en_male_sing_funny_it_goes_up.mp3 +Song,Song: Jingle (Lobby),male,en_male_m03_lobby,This is an example sentence in English.,/audio/en_male_m03_lobby.mp3 +Song,Song: Melodrama (Wonderful World),female,en_female_ht_f08_wonderful_world,This is an example sentence in English.,/audio/en_female_ht_f08_wonderful_world.mp3 +Song,Song: NYE 2023,female,en_female_ht_f08_newyear,This is an example sentence in English.,/audio/en_female_ht_f08_newyear.mp3 +Song,Song: Thanksgiving,male,en_male_sing_funny_thanksgiving,This is an example sentence in English.,/audio/en_male_sing_funny_thanksgiving.mp3 +Song,Song: Toon Beat (Sunshine Soon),male,en_male_m03_sunshine_soon,This is an example sentence in English.,/audio/en_male_m03_sunshine_soon.mp3 +Song,Song: Pop Lullaby,female,en_female_f08_twinkle,This is an example sentence in English.,/audio/en_female_f08_twinkle.mp3 +Song,Song: Quirky Time,male,en_male_m2_xhxs_m03_silly,This is an example sentence in English.,/audio/en_male_m2_xhxs_m03_silly.mp3 +French,French Male 1,male,fr_001,Ceci est une phrase exemple en français.,/audio/fr_001.mp3 +French,French Male 2,male,fr_002,Ceci est une phrase exemple en français.,/audio/fr_002.mp3 +German,German Female,female,de_001,Dies ist ein Beispielsatz auf Deutsch.,/audio/de_001.mp3 +German,German Male,male,de_002,Dies ist ein Beispielsatz auf Deutsch.,/audio/de_002.mp3 +Indonesian,Darma,male,id_male_darma,Ini adalah kalimat contoh dalam bahasa Indonesia.,/audio/id_male_darma.mp3 +Indonesian,Icha,female,id_female_icha,Ini adalah kalimat contoh dalam bahasa Indonesia.,/audio/id_female_icha.mp3 +Indonesian,Noor,female,id_female_noor,Ini adalah kalimat contoh dalam bahasa Indonesia.,/audio/id_female_noor.mp3 +Indonesian,Putra,male,id_male_putra,Ini adalah kalimat contoh dalam bahasa Indonesia.,/audio/id_male_putra.mp3 +Italian,Italian Male,male,it_male_m18,Questa è una frase di esempio in italiano.,/audio/it_male_m18.mp3 +Japanese,Miho,neutral,jp_001,これは日本語の例文です。,/audio/jp_001.mp3 +Japanese,Keiko,neutral,jp_003,これは日本語の例文です。,/audio/jp_003.mp3 +Japanese,Sakura,neutral,jp_005,これは日本語の例文です。,/audio/jp_005.mp3 +Japanese,Naoki,neutral,jp_006,これは日本語の例文です。,/audio/jp_006.mp3 +Japanese,Morisuke,male,jp_male_osada,これは日本語の例文です。,/audio/jp_male_osada.mp3 +Japanese,Matsuo,male,jp_male_matsuo,これは日本語の例文です。,/audio/jp_male_matsuo.mp3 +Japanese,Machikoriiita,female,jp_female_machikoriiita,これは日本語の例文です。,/audio/jp_female_machikoriiita.mp3 +Japanese,Matsudake,male,jp_male_matsudake,これは日本語の例文です。,/audio/jp_male_matsudake.mp3 +Japanese,Shuichiro,male,jp_male_shuichiro,これは日本語の例文です。,/audio/jp_male_shuichiro.mp3 +Japanese,Maruyama Rei,female,jp_female_rei,これは日本語の例文です。,/audio/jp_female_rei.mp3 +Japanese,Hikakin,male,jp_male_hikakin,これは日本語の例文です。,/audio/jp_male_hikakin.mp3 +Japanese,Yagi Saki,female,jp_female_yagishaki,これは日本語の例文です。,/audio/jp_female_yagishaki.mp3 +Korean,Korean Male 1,male,kr_002,이것은 한국어 예문입니다.,/audio/kr_002.mp3 +Korean,Korean Male 2,male,kr_004,이것은 한국어 예문입니다.,/audio/kr_004.mp3 +Korean,Korean Female,female,kr_003,이것은 한국어 예문입니다.,/audio/kr_003.mp3 +Portuguese,Julia,neutral,br_003,Esta é uma frase de exemplo em português.,/audio/br_003.mp3 +Portuguese,Ana,neutral,br_004,Esta é uma frase de exemplo em português.,/audio/br_004.mp3 +Portuguese,Lucas,neutral,br_005,Esta é uma frase de exemplo em português.,/audio/br_005.mp3 +Portuguese,Lhays Macedo,female,pt_female_lhays,Esta é uma frase de exemplo em português.,/audio/pt_female_lhays.mp3 +Portuguese,Laizza,female,pt_female_laizza,Esta é uma frase de exemplo em português.,/audio/pt_female_laizza.mp3 +Portuguese,Optimus Prime (Portuguese),male,pt_male_transformer,Esta é uma frase de exemplo em português.,/audio/pt_male_transformer.mp3 +Spanish,Spanish Male,male,es_002,Esta es una oración de ejemplo en español.,/audio/es_002.mp3 +Spanish,Julio,male,es_male_m3,Esta es una oración de ejemplo en español.,/audio/es_male_m3.mp3 +Spanish,Alejandra,female,es_female_f6,Esta es una oración de ejemplo en español.,/audio/es_female_f6.mp3 +Spanish,Mariana,female,es_female_fp1,Esta es una oración de ejemplo en español.,/audio/es_female_fp1.mp3 +Spanish,Álex (Warm),neutral,es_mx_002,Esta es una oración de ejemplo en español.,/audio/es_mx_002.mp3 +Spanish,Optimus Prime (Mexican),male,es_mx_male_transformer,Esta es una oración de ejemplo en español.,/audio/es_mx_male_transformer.mp3 +Spanish,Super Mamá,female,es_mx_female_supermom,Esta es una oración de ejemplo en español.,/audio/es_mx_female_supermom.mp3 diff --git a/assets/js/modules/VoiceManager.js b/assets/js/modules/VoiceManager.js index 8db8102..9cbde65 100644 --- a/assets/js/modules/VoiceManager.js +++ b/assets/js/modules/VoiceManager.js @@ -1,11 +1,17 @@ export class VoiceManager { constructor() { this.voiceData = null; + this.selectedVoices = new Set(); this.providerSelect = document.getElementById('tts-provider'); this.googleSelect = document.getElementById('google-voice-select'); this.tiktokSelects = document.getElementById('tiktok-voice-selects'); - this.tiktokLangSelect = document.getElementById('tiktok-language'); - this.tiktokVoiceSelect = document.getElementById('tiktok-voice'); + this.voiceSearch = document.getElementById('voice-search'); + this.languageFilter = document.getElementById('language-filter'); + this.genderFilter = document.getElementById('gender-filter'); + this.voiceList = document.getElementById('voice-list'); + this.selectAllCheckbox = document.getElementById('select-all-voices'); + this.selectedVoiceCount = document.getElementById('selected-voice-count'); + this.clearVoicesBtn = document.getElementById('clear-voices'); this.init(); } @@ -21,7 +27,8 @@ export class VoiceManager { const response = await fetch('/data/tiktok_voice_ids.csv'); const text = await response.text(); this.voiceData = this.parseCSV(text); - this.populateLanguageSelect(); + this.populateLanguageFilter(); + this.populateVoiceList(); } catch (error) { console.error('Failed to load voice data:', error); } @@ -31,37 +38,78 @@ export class VoiceManager { const lines = text.split('\n'); const headers = lines[0].split(','); - return lines.slice(1) + const parsed = lines.slice(1) .filter(line => line.trim()) .map(line => { - const values = line.split(','); - return { + // Handle CSV values that might contain commas within quotes + const values = line.match(/(?:^|,)("(?:[^"]|"")*"|[^,]*)/g) + .map(value => { + // Remove leading comma and quotes, handle escaped quotes + value = value.replace(/^,/, ''); + if (value.startsWith('"') && value.endsWith('"')) { + value = value.slice(1, -1).replace(/""/g, '"'); + } + return value.trim(); + }); + + const result = { lang_label: values[0], voice_name: values[1], - voice_id: values[2].trim() + voice_gender: values[2], + voice_id: values[3], + sample_sentence: values[4] || '', + sample_voice: values[5] ? values[5].replace(/\\n/g, '\n').replace(/\\"/g, '"') : '' }; + console.log('Parsed voice entry:', result); + return result; }); + return parsed; } - populateLanguageSelect() { + populateLanguageFilter() { // Get unique languages const languages = [...new Set(this.voiceData.map(v => v.lang_label))]; - this.tiktokLangSelect.innerHTML = languages + this.languageFilter.innerHTML = '' + languages .map(lang => ``) .join(''); - - // Trigger voice population for initial language - this.populateVoiceSelect(languages[0]); } - populateVoiceSelect(language) { - const voices = this.voiceData.filter(v => v.lang_label === language); - - this.tiktokVoiceSelect.innerHTML = - '' + - voices.map(v => ``) - .join(''); + populateVoiceList() { + this.voiceList.innerHTML = this.voiceData + .map(voice => ` + + + + + ${voice.lang_label} + ${voice.voice_name} + ${voice.voice_gender} + + + + + `).join(''); + + // Delegate the click event to the table body + $(this.voiceList).off('click', '.voice-row td').on('click', '.voice-row td', (e) => { + // Skip if clicking the sample cell or checkbox + if ($(e.target).closest('.sample-cell').length || $(e.target).is(':checkbox')) { + return; + } + + const $row = $(e.target).closest('.voice-row'); + const $checkbox = $row.find(':checkbox'); + const newState = !$checkbox.prop('checked'); + + $checkbox.prop('checked', newState); + this.toggleVoice($row.data('voice-id'), newState); + }); } setupEventListeners() { @@ -69,9 +117,118 @@ export class VoiceManager { this.updateVoiceUI(e.target.value); }); - this.tiktokLangSelect.addEventListener('change', (e) => { - this.populateVoiceSelect(e.target.value); + this.voiceSearch.addEventListener('input', () => this.filterVoices()); + this.languageFilter.addEventListener('change', () => this.filterVoices()); + this.genderFilter.addEventListener('change', () => this.filterVoices()); + + this.selectAllCheckbox.addEventListener('change', (e) => { + const checkboxes = this.voiceList.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(checkbox => { + checkbox.checked = e.target.checked; + this.toggleVoice(checkbox.value, e.target.checked); + }); + this.updateVoiceCount(); }); + + if (this.clearVoicesBtn) { + this.clearVoicesBtn.addEventListener('click', () => { + this.selectedVoices.clear(); + this.selectAllCheckbox.checked = false; + const checkboxes = this.voiceList.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(checkbox => { + checkbox.checked = false; + }); + this.updateVoiceCount(); + }); + } + } + + toggleVoice(voiceId, selected) { + if (selected) { + this.selectedVoices.add(voiceId); + } else { + this.selectedVoices.delete(voiceId); + } + this.updateVoiceCount(); + } + + updateVoiceCount() { + if (this.selectedVoiceCount) { + this.selectedVoiceCount.textContent = this.selectedVoices.size; + } + } + + filterVoices() { + const searchTerm = this.voiceSearch.value.toLowerCase(); + const languageFilter = this.languageFilter.value; + const genderFilter = this.genderFilter.value; + + // Filter the data + const filteredData = this.voiceData.filter(voice => { + const matchesSearch = + voice.voice_name.toLowerCase().includes(searchTerm) || + voice.lang_label.toLowerCase().includes(searchTerm); + const matchesLanguage = + languageFilter === 'all' || + voice.lang_label === languageFilter; + const matchesGender = + genderFilter === 'all' || + voice.voice_gender.toLowerCase() === genderFilter; + return matchesSearch && matchesLanguage && matchesGender; + }); + + // Update the voiceData reference and repopulate + this.populateVoiceList(filteredData); + } + + populateVoiceList(data = this.voiceData) { + this.voiceList.innerHTML = this.voiceData + .map(voice => ` + + + + + ${voice.lang_label} + ${voice.voice_name} + ${voice.voice_gender} + + + + + `).join(''); + + // Delegate the click event to the table body + $(this.voiceList).off('click', '.voice-row td').on('click', '.voice-row td', (e) => { + // Skip if clicking the sample cell or checkbox + if ($(e.target).closest('.sample-cell').length || $(e.target).is(':checkbox')) { + return; + } + + const $row = $(e.target).closest('.voice-row'); + const $checkbox = $row.find(':checkbox'); + const newState = !$checkbox.prop('checked'); + + $checkbox.prop('checked', newState); + this.toggleVoice($row.data('voice-id'), newState); + }); + } + + async playSample(samplePath) { + console.log('Attempting to play sample:', { + rawPath: samplePath, + type: typeof samplePath + }); + const audio = new Audio(samplePath); + try { + await audio.play(); + } catch (error) { + console.error('Error playing sample:', error); + } } updateVoiceUI(provider) { @@ -87,16 +244,11 @@ export class VoiceManager { getCurrentVoiceId() { const provider = this.providerSelect.value; if (provider === 'tiktok') { - if (this.tiktokVoiceSelect.value === 'random') { - // Get all voice IDs for current language - const currentLang = this.tiktokLangSelect.value; - const voices = this.voiceData.filter(v => v.lang_label === currentLang); - // Pick a random voice - const randomIndex = Math.floor(Math.random() * voices.length); - return voices[randomIndex].voice_id; - } else { - return this.tiktokVoiceSelect.value; + if (this.selectedVoices.size === 0) { + return this.voiceData[0].voice_id; // Default to first voice if none selected } + const voiceIds = Array.from(this.selectedVoices); + return voiceIds[Math.floor(Math.random() * voiceIds.length)]; } return document.getElementById('tts-language').value; }