WolfDavid commited on
Commit
94dba69
·
1 Parent(s): b88e7d3

feat(voice): switch the avatar voice to 雨晴はう (VOICEVOX style 10)

Browse files

- SPEAKER_STYLE_ID 3 -> 10 and CREDIT_STRING "VOICEVOX:雨晴はう" in voice/tts.py; the
model file keeps its historical zundamon.vvm name (upstream 0.vvm carries all four voices)
- ZUNDAMON_TERMS_URL -> AMEHARE_TERMS_URL (https://amehau.com/?page_id=225) in ui/blocks.py,
wired into the terms notice and the About panel; About names Amehare Project
- Tests re-pinned: SPEAKER_STYLE_ID == 10, AMEHARE_TERMS_HOST in test_credits_visible, the
credit assertion and the fixture docstrings
- LICENSES.md credits block and README credits read VOICEVOX:雨晴はう so the ledger, the page
and the deployed assertion move together

LICENSES.md CHANGED
@@ -78,7 +78,7 @@ The credit strings the page must render (`tests/e2e/test_avatar_loop.py::test_cr
78
  checks the footer, the About panel and the server-delivered config for them):
79
 
80
  ```credits
81
- voice: VOICEVOX:ずんだもん
82
  avatar: VRM1_Constraint_Twist_Sample (c) 2022 pixiv Inc. - VRM Public License 1.0
83
  dictionary: Dictionary: JMdict (EDRDG, CC BY-SA 4.0)
84
  jlpt: JLPT levels: Jonathan Waller's JLPT Resources via stephenmk/yomitan-jlpt-vocab
 
78
  checks the footer, the About panel and the server-delivered config for them):
79
 
80
  ```credits
81
+ voice: VOICEVOX:雨晴はう
82
  avatar: VRM1_Constraint_Twist_Sample (c) 2022 pixiv Inc. - VRM Public License 1.0
83
  dictionary: Dictionary: JMdict (EDRDG, CC BY-SA 4.0)
84
  jlpt: JLPT levels: Jonathan Waller's JLPT Resources via stephenmk/yomitan-jlpt-vocab
README.md CHANGED
@@ -67,10 +67,10 @@ uv run pytest tests/e2e/ -q # browser suite (run it whole, neve
67
  The in-app footer and About panel are the binding credit surfaces; this section mirrors
68
  them so the Space's own page carries the same strings.
69
 
70
- - **Voice: VOICEVOX:ずんだもん** — speech is synthesised with
71
- [VOICEVOX CORE](https://voicevox.hiroshiba.jp/term/) (software terms) using the ずんだもん
72
- voice by SSS LLC ([character terms](https://zunko.jp/con_ongen_kiyaku.html)).
73
- *Synthesised audio is provided under the VOICEVOX and VOICEVOX:ずんだもん terms of use; by
74
  using it you agree to comply with them.*
75
  - **Avatar: VRM1_Constraint_Twist_Sample (c) 2022 pixiv Inc. — VRM Public License 1.0**
76
  ([terms](https://vrm.dev/licenses/1.0/)), from the official VRM specification samples. The
 
67
  The in-app footer and About panel are the binding credit surfaces; this section mirrors
68
  them so the Space's own page carries the same strings.
69
 
70
+ - **Voice: VOICEVOX:雨晴はう** — speech is synthesised with
71
+ [VOICEVOX CORE](https://voicevox.hiroshiba.jp/term/) (software terms) using the 雨晴はう
72
+ voice by Amehare Project ([character terms](https://amehau.com/?page_id=225)).
73
+ *Synthesised audio is provided under the VOICEVOX and VOICEVOX:雨晴はう terms of use; by
74
  using it you agree to comply with them.*
75
  - **Avatar: VRM1_Constraint_Twist_Sample (c) 2022 pixiv Inc. — VRM Public License 1.0**
76
  ([terms](https://vrm.dev/licenses/1.0/)), from the official VRM specification samples. The
src/japanese_avatar/ui/blocks.py CHANGED
@@ -76,7 +76,7 @@ SPEED_MAX = 2.0
76
  SLOWER_SPEED = 0.75
77
 
78
  VOICEVOX_TERMS_URL = "https://voicevox.hiroshiba.jp/term/"
79
- ZUNDAMON_TERMS_URL = "https://zunko.jp/con_ongen_kiyaku.html"
80
  VRM_TERMS_URL = "https://vrm.dev/licenses/1.0/"
81
  VRM_CREDIT = "VRM1_Constraint_Twist_Sample (c) 2022 pixiv Inc. - VRM Public License 1.0"
82
 
@@ -417,8 +417,10 @@ ASR_BADGE_HTML = (
417
  '<div id="asr-tier-text" class="asr-badge">ASR: loads in your browser on the first push</div>'
418
  )
419
 
420
- # DPLY-04. The exact string VOICEVOX:ずんだもん, ASCII colon, no spaces - the form the character
421
- # terms give as their example - always visible, with no interaction. The VRM credit is voluntary
 
 
422
  # (creditNotation: unnecessary) and carried anyway. See docs/VOICEVOX-SETUP.md and docs/ASSETS.md.
423
  # Plan 02-11 adds the three Phase 2 credits beside them: the dictionary credit is REQUIRED on
424
  # every screen display by the EDRDG licence, the JLPT credit by Waller's CC BY, and the
@@ -436,19 +438,19 @@ TERMS_NOTICE_HTML = (
436
  '<div id="terms-notice-text" class="terms-notice">'
437
  f"Synthesised audio is provided under the "
438
  f'<a href="{VOICEVOX_TERMS_URL}" target="_blank" rel="noopener">VOICEVOX</a> and '
439
- f'<a href="{ZUNDAMON_TERMS_URL}" target="_blank" rel="noopener">{CREDIT_STRING}</a> '
440
  "terms of use; by using it you agree to comply with them."
441
  "</div>"
442
  )
443
 
444
  # The 「アプリの紹介画面」 the character terms ask for: an about screen, findable with a little
445
- # looking, carrying the full credit set - VOICEVOX:ずんだもん again, the VRM, the dictionary and
446
  # the runtime libraries. Open on first load so it is on the introduction screen rather than
447
  # behind a click.
448
  ABOUT_MD = f"""\
449
  **Voice** - {CREDIT_STRING}. Speech is synthesised with
450
- [VOICEVOX CORE]({VOICEVOX_TERMS_URL}) (software terms) using the ずんだもん voice by SSS LLC
451
- ([character terms]({ZUNDAMON_TERMS_URL})). The synthesised audio is provided under both sets of
452
  terms; by using it you agree to comply with them.
453
 
454
  **Avatar** - {VRM_CREDIT}. Source: the official VRM specification samples
 
76
  SLOWER_SPEED = 0.75
77
 
78
  VOICEVOX_TERMS_URL = "https://voicevox.hiroshiba.jp/term/"
79
+ AMEHARE_TERMS_URL = "https://amehau.com/?page_id=225"
80
  VRM_TERMS_URL = "https://vrm.dev/licenses/1.0/"
81
  VRM_CREDIT = "VRM1_Constraint_Twist_Sample (c) 2022 pixiv Inc. - VRM Public License 1.0"
82
 
 
417
  '<div id="asr-tier-text" class="asr-badge">ASR: loads in your browser on the first push</div>'
418
  )
419
 
420
+ # DPLY-04. The exact string VOICEVOX:雨晴はう, ASCII colon, no spaces - the form the character
421
+ # terms give as their example; the VOICEVOX credit is mandatory under those terms and the
422
+ # character name is optional-but-welcomed, so this one string satisfies both - always visible,
423
+ # with no interaction. The VRM credit is voluntary
424
  # (creditNotation: unnecessary) and carried anyway. See docs/VOICEVOX-SETUP.md and docs/ASSETS.md.
425
  # Plan 02-11 adds the three Phase 2 credits beside them: the dictionary credit is REQUIRED on
426
  # every screen display by the EDRDG licence, the JLPT credit by Waller's CC BY, and the
 
438
  '<div id="terms-notice-text" class="terms-notice">'
439
  f"Synthesised audio is provided under the "
440
  f'<a href="{VOICEVOX_TERMS_URL}" target="_blank" rel="noopener">VOICEVOX</a> and '
441
+ f'<a href="{AMEHARE_TERMS_URL}" target="_blank" rel="noopener">{CREDIT_STRING}</a> '
442
  "terms of use; by using it you agree to comply with them."
443
  "</div>"
444
  )
445
 
446
  # The 「アプリの紹介画面」 the character terms ask for: an about screen, findable with a little
447
+ # looking, carrying the full credit set - VOICEVOX:雨晴はう again, the VRM, the dictionary and
448
  # the runtime libraries. Open on first load so it is on the introduction screen rather than
449
  # behind a click.
450
  ABOUT_MD = f"""\
451
  **Voice** - {CREDIT_STRING}. Speech is synthesised with
452
+ [VOICEVOX CORE]({VOICEVOX_TERMS_URL}) (software terms) using the 雨晴はう voice by Amehare Project
453
+ ([character terms]({AMEHARE_TERMS_URL})). The synthesised audio is provided under both sets of
454
  terms; by using it you agree to comply with them.
455
 
456
  **Avatar** - {VRM_CREDIT}. Source: the official VRM specification samples
src/japanese_avatar/voice/tts.py CHANGED
@@ -38,19 +38,24 @@ from japanese_avatar.voice.models import SynthResult, TurnTimings
38
  if TYPE_CHECKING: # pragma: no cover - typing only, never imported at runtime
39
  from voicevox_core.blocking import Synthesizer
40
 
41
- #: ずんだもん, style ノーマル. Resolved from the voicevox_vvm 0.17.0 release's own character/style
42
- #: table and confirmed against the metas.json inside voicevox/model/zundamon.vvm.
43
- #: The same file also carries 四国めたん (2), 春日部つむぎ (8) and 雨晴はう (10); only ずんだもん is
44
- #: credited and used. See docs/VOICEVOX-SETUP.md.
45
- SPEAKER_STYLE_ID = 3
46
-
47
- #: Rendered persistently in the UI. Required by the character terms; also required on its own by
48
- #: merely consuming the AudioQuery, so it survives any future engine swap.
49
- CREDIT_STRING = "VOICEVOX:ずんだもん"
 
 
50
 
51
  _SETUP_DOC = "docs/VOICEVOX-SETUP.md"
52
 
53
  _DEFAULT_DICT_DIR = "voicevox/open_jtalk_dic_utf_8-1.11"
 
 
 
54
  _DEFAULT_VVM_PATH = "voicevox/model/zundamon.vvm"
55
  _DEFAULT_ORT_DIR = "voicevox_runtime"
56
 
 
38
  if TYPE_CHECKING: # pragma: no cover - typing only, never imported at runtime
39
  from voicevox_core.blocking import Synthesizer
40
 
41
+ #: 雨晴はう, style ノーマル (speaker uuid 3474ee95-c274-47f9-aa1a-8322163d96f1). Resolved from the
42
+ #: voicevox_vvm 0.17.0 release's own character/style table and confirmed against the metas.json
43
+ #: inside voicevox/model/zundamon.vvm. The same file also carries 四国めたん (2), ずんだもん (3) and
44
+ #: 春日部つむぎ (8); only 雨晴はう is credited and used. See docs/VOICEVOX-SETUP.md.
45
+ SPEAKER_STYLE_ID = 10
46
+
47
+ #: Rendered persistently in the UI. The character terms make the VOICEVOX credit mandatory
48
+ #: (「VOICEVOXのクレジット記載は必須となります」) and the character name optional-but-welcomed; this
49
+ #: form - the terms' own example, ASCII colon, no spaces - satisfies both. It is also required on
50
+ #: its own by merely consuming the AudioQuery, so it survives any future engine swap.
51
+ CREDIT_STRING = "VOICEVOX:雨晴はう"
52
 
53
  _SETUP_DOC = "docs/VOICEVOX-SETUP.md"
54
 
55
  _DEFAULT_DICT_DIR = "voicevox/open_jtalk_dic_utf_8-1.11"
56
+ # zundamon.vvm is a historical filename (chosen when ずんだもん was the speaker): the file is
57
+ # upstream voicevox_vvm 0.17.0's 0.vvm and carries all four voices, so the voice switch did not
58
+ # rename it.
59
  _DEFAULT_VVM_PATH = "voicevox/model/zundamon.vvm"
60
  _DEFAULT_ORT_DIR = "voicevox_runtime"
61
 
tests/e2e/test_avatar_loop.py CHANGED
@@ -523,7 +523,7 @@ def test_ptt_turn(
523
  ):
524
  """VOIC-02. Hold the button, speak Japanese: a transcript appears and the avatar answers.
525
 
526
- The microphone is the ずんだもん speech fixture. Phase 1's bar is that a non-empty
527
  transcript renders, not that it is correct - the ASR model choice is 01-07's measured
528
  decision and real-speech accuracy is a later phase's question.
529
  """
@@ -886,7 +886,7 @@ def test_asr_wasm_fallback(
886
  # The exact flow-down sentence rendered next to the Replay control (blocks.py).
887
  FLOW_DOWN_SENTENCE = "by using it you agree to comply with them"
888
  VOICEVOX_TERMS_HOST = "voicevox.hiroshiba.jp/term"
889
- ZUNDAMON_TERMS_HOST = "zunko.jp/con_ongen_kiyaku.html"
890
  # Plan 02-11. The links the Phase 2 licences require on the About screen, by the fragment of
891
  # the href that identifies each one: the EDRDG licence/project pages (the attribution the
892
  # JMdict licence asks a WWW server and an app "About" screen to carry), Waller's site (his
@@ -965,7 +965,7 @@ def test_credits_visible(page, space_url, warm_space):
965
  """
966
  credits = licenses_block("credits")
967
  voice = credits["voice"]
968
- assert voice == "VOICEVOX:ずんだもん", f"LICENSES.md declares the voice credit as {voice!r}"
969
  assert set(credits) >= {"voice", "avatar", "dictionary", "jlpt", "translation"}, (
970
  f"LICENSES.md ```credits block lost a key: {sorted(credits)}"
971
  )
@@ -984,7 +984,7 @@ def test_credits_visible(page, space_url, warm_space):
984
  assert voice in notice_text
985
  notice_links = notice.locator("a").evaluate_all("els => els.map((e) => e.href)")
986
  assert any(VOICEVOX_TERMS_HOST in h for h in notice_links), notice_links
987
- assert any(ZUNDAMON_TERMS_HOST in h for h in notice_links), notice_links
988
 
989
  replay = page.locator("#replay-button")
990
  assert replay.is_visible()
@@ -1005,7 +1005,7 @@ def test_credits_visible(page, space_url, warm_space):
1005
  about_text = about.inner_text()
1006
  about_links = about.locator("a").evaluate_all("els => els.map((e) => e.href)")
1007
  assert any(VOICEVOX_TERMS_HOST in h for h in about_links), about_links
1008
- assert any(ZUNDAMON_TERMS_HOST in h for h in about_links), about_links
1009
 
1010
  # The attribution links the Phase 2 licences require, each named by LICENSES.md.
1011
  missing_links = [
 
523
  ):
524
  """VOIC-02. Hold the button, speak Japanese: a transcript appears and the avatar answers.
525
 
526
+ The microphone is the 雨晴はう speech fixture. Phase 1's bar is that a non-empty
527
  transcript renders, not that it is correct - the ASR model choice is 01-07's measured
528
  decision and real-speech accuracy is a later phase's question.
529
  """
 
886
  # The exact flow-down sentence rendered next to the Replay control (blocks.py).
887
  FLOW_DOWN_SENTENCE = "by using it you agree to comply with them"
888
  VOICEVOX_TERMS_HOST = "voicevox.hiroshiba.jp/term"
889
+ AMEHARE_TERMS_HOST = "amehau.com/?page_id=225"
890
  # Plan 02-11. The links the Phase 2 licences require on the About screen, by the fragment of
891
  # the href that identifies each one: the EDRDG licence/project pages (the attribution the
892
  # JMdict licence asks a WWW server and an app "About" screen to carry), Waller's site (his
 
965
  """
966
  credits = licenses_block("credits")
967
  voice = credits["voice"]
968
+ assert voice == "VOICEVOX:雨晴はう", f"LICENSES.md declares the voice credit as {voice!r}"
969
  assert set(credits) >= {"voice", "avatar", "dictionary", "jlpt", "translation"}, (
970
  f"LICENSES.md ```credits block lost a key: {sorted(credits)}"
971
  )
 
984
  assert voice in notice_text
985
  notice_links = notice.locator("a").evaluate_all("els => els.map((e) => e.href)")
986
  assert any(VOICEVOX_TERMS_HOST in h for h in notice_links), notice_links
987
+ assert any(AMEHARE_TERMS_HOST in h for h in notice_links), notice_links
988
 
989
  replay = page.locator("#replay-button")
990
  assert replay.is_visible()
 
1005
  about_text = about.inner_text()
1006
  about_links = about.locator("a").evaluate_all("els => els.map((e) => e.href)")
1007
  assert any(VOICEVOX_TERMS_HOST in h for h in about_links), about_links
1008
+ assert any(AMEHARE_TERMS_HOST in h for h in about_links), about_links
1009
 
1010
  # The attribution links the Phase 2 licences require, each named by LICENSES.md.
1011
  missing_links = [
tests/e2e/test_stage_standalone.py CHANGED
@@ -179,7 +179,7 @@ def test_arms_rest_at_sides(page, static_server):
179
 
180
 
181
  def test_demo_timeline_drives_visemes(page, static_server):
182
- """A generated timeline against the real ずんだもん WAV, clocked off the AudioContext.
183
 
184
  Since plan 01-06 the demo timeline is produced by ``visemes.build_timeline`` from a real
185
  ``AudioQuery`` and the audio is the matching synthesis, so this is no longer a plausible
 
179
 
180
 
181
  def test_demo_timeline_drives_visemes(page, static_server):
182
+ """A generated timeline against the real 雨晴はう WAV, clocked off the AudioContext.
183
 
184
  Since plan 01-06 the demo timeline is produced by ``visemes.build_timeline`` from a real
185
  ``AudioQuery`` and the audio is the matching synthesis, so this is no longer a plausible
tests/test_tts_contract.py CHANGED
@@ -105,7 +105,7 @@ def test_speed_scale_lengthens_audio(synth):
105
  def test_output_sampling_rate_is_24000(short_result):
106
  """93.75 fps in plan 01-06 is exactly 24000 / 256; the rate is load-bearing, not incidental."""
107
  assert short_result.audio_query["outputSamplingRate"] == 24000
108
- assert SPEAKER_STYLE_ID == 3
109
 
110
 
111
  def test_fixtures_match_current_engine(synth_meta, synth):
 
105
  def test_output_sampling_rate_is_24000(short_result):
106
  """93.75 fps in plan 01-06 is exactly 24000 / 256; the rate is load-bearing, not incidental."""
107
  assert short_result.audio_query["outputSamplingRate"] == 24000
108
+ assert SPEAKER_STYLE_ID == 10
109
 
110
 
111
  def test_fixtures_match_current_engine(synth_meta, synth):