@minimalcorp/tsunagi 0.1.48 → 0.1.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
  2. package/.next/standalone/apps/web/.next/build-manifest.json +5 -5
  3. package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/apps/web/.next/server/app/_global-error/page/build-manifest.json +2 -2
  5. package/.next/standalone/apps/web/.next/server/app/_global-error/page.js +1 -1
  6. package/.next/standalone/apps/web/.next/server/app/_global-error/page.js.nft.json +1 -1
  7. package/.next/standalone/apps/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/apps/web/.next/server/app/_not-found/page/build-manifest.json +2 -2
  16. package/.next/standalone/apps/web/.next/server/app/_not-found/page.js +1 -1
  17. package/.next/standalone/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  18. package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
  20. package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +13 -13
  21. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
  22. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  23. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +8 -8
  24. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  25. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  26. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  27. package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
  28. package/.next/standalone/apps/web/.next/server/app/index.rsc +15 -15
  29. package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  30. package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +15 -15
  31. package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +4 -4
  32. package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +8 -8
  33. package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  34. package/.next/standalone/apps/web/.next/server/app/page/build-manifest.json +2 -2
  35. package/.next/standalone/apps/web/.next/server/app/page.js +1 -1
  36. package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
  37. package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  38. package/.next/standalone/apps/web/.next/server/app/settings/page/build-manifest.json +2 -2
  39. package/.next/standalone/apps/web/.next/server/app/settings/page.js +1 -1
  40. package/.next/standalone/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  41. package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
  43. package/.next/standalone/apps/web/.next/server/app/settings.rsc +15 -15
  44. package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +15 -15
  45. package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  46. package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +8 -8
  47. package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  48. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  49. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  50. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page/build-manifest.json +2 -2
  51. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page.js +5 -4
  52. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  53. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0h4wzcb._.js → [root-of-the-server]__0.c7m6m._.js} +2 -2
  55. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__02o_btn._.js +9 -0
  56. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__08uda78._.js +3 -0
  57. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0jj9045._.js +3 -0
  58. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__09m_0f6._.js → [root-of-the-server]__0kpobap._.js} +2 -2
  59. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0m52zsj._.js +3 -0
  60. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0mo_9ei._.js +1 -1
  61. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0stter-._.js +4 -0
  62. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__11y.qj~._.js +3 -0
  63. package/.next/standalone/apps/web/.next/server/chunks/ssr/_00mhd_n._.js +7 -0
  64. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0g.cd6a._.js +1 -1
  65. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0i7y5ac._.js +3 -0
  66. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0iscwmf._.js +14 -0
  67. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0ldtf2a._.js +7 -0
  68. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0ydcfna._.js +3 -0
  69. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0z8pikg._.js +7 -0
  70. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0zu_05y._.js +3 -0
  71. package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_settings_page_tsx_0i6itlb._.js +1 -1
  72. package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_tasks_[id]_page_tsx_0jshsm2._.js +12 -12
  73. package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_tasks_layout_tsx_02s00ls._.js +3 -0
  74. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0qvxljj._.js → node_modules_0-5m30v._.js} +1 -1
  75. package/.next/standalone/apps/web/.next/server/chunks/ssr/node_modules_0-bra0k._.js +3 -0
  76. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0zir34w._.js → node_modules_0-nk4sk._.js} +1 -1
  77. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0dmu3re._.js → node_modules_0-yxz.k._.js} +1 -1
  78. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0p8a~x3._.js → node_modules_01l-p1x._.js} +1 -1
  79. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0pksdi6._.js → node_modules_053ofle._.js} +1 -1
  80. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_04g5ove._.js → node_modules_0azs4bs._.js} +1 -1
  81. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_049fpp9._.js → node_modules_0br2zvr._.js} +1 -1
  82. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0akt-n8._.js → node_modules_0g-5xh6._.js} +1 -1
  83. package/.next/standalone/apps/web/.next/server/chunks/ssr/node_modules_0k6b-s.._.js +6 -0
  84. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0bvpcr6._.js → node_modules_0kuu0i_._.js} +1 -1
  85. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0gq_a6h._.js → node_modules_0ljm1cj._.js} +1 -1
  86. package/.next/standalone/apps/web/.next/server/chunks/ssr/node_modules_0mogzs3._.js +6 -0
  87. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0v6uk6x._.js → node_modules_0ne-fkd._.js} +1 -1
  88. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0soq_if._.js → node_modules_0rgnv~i._.js} +1 -1
  89. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0b48qku._.js → node_modules_0s5.073._.js} +1 -1
  90. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_076bd-f._.js → node_modules_0wg2e2t._.js} +1 -1
  91. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0bnsxo_._.js → node_modules_0zxpl-b._.js} +1 -1
  92. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0ydrd8p._.js → node_modules_10vm5h.._.js} +1 -1
  93. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_10xgk_8.js → node_modules_next_dist_esm_build_templates_app-page_061~hf9.js} +3 -3
  94. package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +5 -5
  95. package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
  96. package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
  97. package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
  98. package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
  99. package/.next/standalone/apps/web/.next/static/chunks/0.ahnhx-ugzbt.js +7 -0
  100. package/.next/standalone/apps/web/.next/static/chunks/01fuewnm93_l5.js +1 -0
  101. package/.next/standalone/apps/web/.next/static/chunks/0bhssqb0~3~7n.js +23 -0
  102. package/.next/standalone/apps/web/.next/static/chunks/0ekz145m0f5h8.js +1 -0
  103. package/.next/standalone/apps/web/.next/static/chunks/0makl-d3f0_qh.js +2878 -0
  104. package/.next/standalone/apps/web/.next/static/chunks/0mtq6r6l61k.f.js +31 -0
  105. package/.next/standalone/apps/web/.next/static/chunks/0n.xodexdkf03.js +1 -0
  106. package/.next/standalone/apps/web/.next/static/chunks/0ohaa3~lhhv1b.js +5 -0
  107. package/.next/standalone/apps/web/.next/static/chunks/0p19bzg3v08hf.js +1 -0
  108. package/.next/standalone/apps/web/.next/static/chunks/0pg.320d4u8z5.js +1 -0
  109. package/.next/standalone/apps/web/.next/static/chunks/0plamn018wq.u.css +4 -0
  110. package/.next/standalone/apps/web/.next/static/chunks/0qbchjvhms-.9.js +5 -0
  111. package/.next/standalone/apps/web/.next/static/chunks/{0pfyw6txeoy_p.js → 0tcznr_934_ai.js} +8 -8
  112. package/.next/standalone/apps/web/.next/static/chunks/0ywpi-uf71k8s.js +1 -0
  113. package/.next/standalone/apps/web/.next/static/chunks/12av8cpq.8slk.js +5 -0
  114. package/.next/standalone/apps/web/.next/static/chunks/12n4j5ugu5jbn.js +12 -0
  115. package/.next/standalone/apps/web/.next/static/chunks/16ehoz1y-qf39.js +5 -0
  116. package/.next/standalone/apps/web/.next/static/chunks/{turbopack-07pr2uza0.4cp.js → turbopack-0s_.rdhg458.a.js} +1 -1
  117. package/.next/standalone/apps/web/package.json +3 -0
  118. package/.next/standalone/apps/web/public/vad/ort-wasm-simd-threaded.mjs +59 -0
  119. package/.next/standalone/apps/web/public/vad/ort-wasm-simd-threaded.wasm +0 -0
  120. package/.next/standalone/apps/web/public/vad/silero_vad_v5.onnx +0 -0
  121. package/.next/standalone/apps/web/public/vad/vad.worklet.bundle.min.js +1 -0
  122. package/dist/server/routes/tasks.js +9 -0
  123. package/dist/server/routes/whisper.js +8 -1
  124. package/dist/whisper-server/README.md +1 -1
  125. package/dist/whisper-server/server.py +54 -9
  126. package/npm-shrinkwrap.json +2 -2
  127. package/package.json +1 -1
  128. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__00qvk7s._.js +0 -3
  129. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0a8.h72._.js +0 -3
  130. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0d7excn._.js +0 -10
  131. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0n83hx6._.js +0 -3
  132. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w3_4.k._.js +0 -10
  133. package/.next/standalone/apps/web/.next/server/chunks/ssr/_04l3mh~._.js +0 -10
  134. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0_2b4wf._.js +0 -3
  135. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0_3mc_u._.js +0 -14
  136. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0e3431w._.js +0 -10
  137. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0lirkqp._.js +0 -10
  138. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0s18_3n._.js +0 -3
  139. package/.next/standalone/apps/web/.next/static/chunks/04fnr6blquen6.js +0 -7
  140. package/.next/standalone/apps/web/.next/static/chunks/04g3fzo25y9_g.js +0 -23
  141. package/.next/standalone/apps/web/.next/static/chunks/04h-q2fe2awuu.css +0 -4
  142. package/.next/standalone/apps/web/.next/static/chunks/04ie1rttuhc99.js +0 -1
  143. package/.next/standalone/apps/web/.next/static/chunks/05n6~h_wwg.jj.js +0 -5
  144. package/.next/standalone/apps/web/.next/static/chunks/06l-vwr5pldup.js +0 -12
  145. package/.next/standalone/apps/web/.next/static/chunks/06sk6d3k059.n.js +0 -1
  146. package/.next/standalone/apps/web/.next/static/chunks/0_ygv4z~5c_9z.js +0 -5
  147. package/.next/standalone/apps/web/.next/static/chunks/0apjd6p1xsnc3.js +0 -31
  148. package/.next/standalone/apps/web/.next/static/chunks/0imnlpmbrdgiv.js +0 -5
  149. package/.next/standalone/apps/web/.next/static/chunks/0z43cogzp17lz.js +0 -7
  150. package/.next/standalone/apps/web/.next/static/chunks/0zjymvayyxt-d.js +0 -5
  151. package/.next/standalone/apps/web/.next/static/chunks/167xa3jy_0g.u.js +0 -1
  152. /package/.next/standalone/apps/web/.next/static/{q_5b0iJOSXBWJiPytDA2j → w7do3hyV84oyognhRCQuA}/_buildManifest.js +0 -0
  153. /package/.next/standalone/apps/web/.next/static/{q_5b0iJOSXBWJiPytDA2j → w7do3hyV84oyognhRCQuA}/_clientMiddlewareManifest.js +0 -0
  154. /package/.next/standalone/apps/web/.next/static/{q_5b0iJOSXBWJiPytDA2j → w7do3hyV84oyognhRCQuA}/_ssgManifest.js +0 -0
@@ -41,9 +41,13 @@ export async function whisperRoutes(fastify) {
41
41
  // whisper-serverのinitial_promptとしてそのまま転送する。
42
42
  const promptField = file.fields.prompt;
43
43
  const prompt = typeof promptField?.value === 'string' ? promptField.value : undefined;
44
+ // 発話中の途中経過表示用のリクエスト。確定前の暫定結果なので、LLM整形と
45
+ // デバッグログはスキップして生の文字起こし結果だけを速く返す。
46
+ const interimField = file.fields.interim;
47
+ const interim = interimField?.value === 'true';
44
48
  // ローカルLLMによる整形を使うかどうかはクライアント(Settingsの有効/無効フラグ)から渡される。
45
49
  const useLlmField = file.fields.useLlm;
46
- const useLlm = useLlmField?.value === 'true';
50
+ const useLlm = !interim && useLlmField?.value === 'true';
47
51
  // LLM整形用システムプロンプトもSettings画面で編集・保存でき、指定があれば
48
52
  // 既定のプロンプトの代わりに使う(空文字列の場合は既定のプロンプトを使う)。
49
53
  const systemPromptField = file.fields.systemPrompt;
@@ -75,6 +79,9 @@ export async function whisperRoutes(fastify) {
75
79
  : 'Transcription failed. Is apps/whisper-server running?',
76
80
  });
77
81
  }
82
+ if (interim) {
83
+ return reply.status(200).send({ text: whisperText });
84
+ }
78
85
  if (!useLlm || !whisperText) {
79
86
  appendVoiceDebugLog({ whisperPrompt: prompt, whisperText, useLlm });
80
87
  return reply.status(200).send({ text: whisperText });
@@ -8,7 +8,7 @@ tsunagi本体はこのサーバーにHTTPでプロキシするだけで、セッ
8
8
  - macOS (Apple Silicon: M1/M2/M3/M4)
9
9
  - Python 3.9+ (Xcode Command Line Tools または Homebrew 経由で入手可能)
10
10
 
11
- ffmpeg等の外部バイナリは不要(音声はブラウザ側で16kHzモノラルWAVに変換して送られる)。
11
+ ffmpeg等の外部バイナリは不要(音声はブラウザ側のVADで発話区間だけ切り出し、16kHzモノラルWAVで送られる)。
12
12
 
13
13
  ## セットアップ・起動
14
14
 
@@ -3,14 +3,14 @@
3
3
  ユーザーが手動でセットアップ・起動する常駐プロセス。モデルをメモリに保持し続け
4
4
  リクエスト毎のロード待ちを避ける。tsunagi本体(Fastify)からHTTPでプロキシされる。
5
5
 
6
- 音声はブラウザのMediaRecorderが生成する元のwebm/opusをそのまま受け取る
7
- (クライアント側でのWAV再エンコードは行わない。Opus圧縮は録音時点で既に
8
- 発生しているため、無圧縮WAVへ変換し直しても音質は改善せず転送量が増えるだけ)。
9
- デコードにはPyAV(`av`)を使う。ffmpegの内部コーデックをホイールに同梱しており、
6
+ 音声はブラウザ側のVAD(Silero VAD)で発話区間だけを切り出した16kHzモノラルWAVを受け取る。
7
+ デコードにはPyAV(`av`)を使う(WAV以外の形式もそのままデコードできる)。ffmpegの内部コーデックをホイールに同梱しており、
10
8
  システムにffmpegバイナリをインストールする必要はない。
11
9
  """
12
10
 
13
11
  import io
12
+ import re
13
+ import threading
14
14
  from typing import Optional
15
15
 
16
16
  import av
@@ -23,6 +23,33 @@ MODEL = "mlx-community/whisper-large-v3-turbo"
23
23
  # 生成してしまう(Whisper系モデルで知られたハルシネーション挙動)ことがあるため、
24
24
  # no_speech_prob(無音である確率)がこの値を超えるセグメントは出力から除外する。
25
25
  NO_SPEECH_THRESHOLD = 0.6
26
+ # ただしno_speech_probは30秒の窓ごとに1回しか計算されず、窓内の全セグメントに同じ値が
27
+ # コピーされる。そのため「発話+末尾の無音」を含む窓では、無音部分から生成された定型文も
28
+ # 発話ありと判定されて素通りする。これを補うため、発話より後ろ(または前)の無音区間に
29
+ # 現れた異常セグメントを読み飛ばすmlx_whisper組込みの判定(要word_timestamps)を有効にする。
30
+ HALLUCINATION_SILENCE_THRESHOLD = 2.0
31
+ # それでも残った場合の最終防衛線。YouTube字幕由来の典型的なハルシネーションで、
32
+ # セグメント全体が(句読点・空白を除いて)これらと完全一致する場合のみ除外する。
33
+ # 部分一致にしないのは、ユーザーが実際にこれらの語を含む文を話すケースを壊さないため。
34
+ HALLUCINATION_PHRASES = {
35
+ "ご視聴ありがとうございました",
36
+ "ご視聴ありがとうございます",
37
+ "最後までご視聴いただきありがとうございました",
38
+ "最後までご視聴ありがとうございました",
39
+ "チャンネル登録お願いします",
40
+ "チャンネル登録をお願いします",
41
+ "チャンネル登録よろしくお願いします",
42
+ "次回もお楽しみに",
43
+ "次回予告",
44
+ "おやすみなさい",
45
+ }
46
+ _NORMALIZE_RE = re.compile(r"[\s、。,.,.!!??・…「」『』()()\[\]〜~♪]+")
47
+
48
+ # mlx_whisperの推論は同時実行を想定していないため直列化する。エンドポイント自体は
49
+ # 同期関数にしてスレッドプールで実行させ、推論中も/healthが応答できるようにする
50
+ # (途中経過の表示で文字起こしリクエストが連続しても、起動状態のポーリングが
51
+ # タイムアウトしてUIが「未起動」扱いになるのを防ぐ)。
52
+ _transcribe_lock = threading.Lock()
26
53
 
27
54
  app = FastAPI()
28
55
 
@@ -49,15 +76,30 @@ def decode_to_16k_mono(data: bytes) -> np.ndarray:
49
76
  return samples
50
77
 
51
78
 
79
+ def is_hallucination_phrase(text: str) -> bool:
80
+ return _NORMALIZE_RE.sub("", text) in HALLUCINATION_PHRASES
81
+
82
+
52
83
  @app.post("/transcribe")
53
- async def transcribe(file: UploadFile = File(...), prompt: Optional[str] = Form(None)) -> dict:
54
- data = await file.read()
84
+ def transcribe(file: UploadFile = File(...), prompt: Optional[str] = Form(None)) -> dict:
85
+ data = file.file.read()
55
86
  audio = decode_to_16k_mono(data)
87
+ if audio.size == 0:
88
+ return {"text": ""}
56
89
  # initial_promptは文字起こしのスタイル(表記ゆれ・句読点・固有名詞など)を
57
90
  # 誘導するヒントで、tsunagiのSettingsからユーザーが自由に設定できる。
58
- result = mlx_whisper.transcribe(
59
- audio, path_or_hf_repo=MODEL, language="ja", initial_prompt=prompt or None
60
- )
91
+ with _transcribe_lock:
92
+ result = mlx_whisper.transcribe(
93
+ audio,
94
+ path_or_hf_repo=MODEL,
95
+ language="ja",
96
+ initial_prompt=prompt or None,
97
+ # 前の窓の出力を次の窓のプロンプトに引き継ぐと、一度出たハルシネーションが
98
+ # 後続の窓へ連鎖しやすくなるため無効化する。
99
+ condition_on_previous_text=False,
100
+ word_timestamps=True,
101
+ hallucination_silence_threshold=HALLUCINATION_SILENCE_THRESHOLD,
102
+ )
61
103
 
62
104
  # result["text"]はno_speech_prob等のフィルタを経ずに全セグメントを結合した
63
105
  # ものなので使わず、セグメント単位でno_speech_probを見て自前で組み立て直す。
@@ -67,8 +109,11 @@ async def transcribe(file: UploadFile = File(...), prompt: Optional[str] = Form(
67
109
  seg["text"]
68
110
  for seg in segments
69
111
  if seg.get("no_speech_prob", 0.0) <= NO_SPEECH_THRESHOLD
112
+ and not is_hallucination_phrase(seg["text"])
70
113
  )
71
114
  else:
72
115
  text = result.get("text", "")
116
+ if is_hallucination_phrase(text):
117
+ text = ""
73
118
 
74
119
  return {"text": text.strip()}
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@minimalcorp/tsunagi",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@minimalcorp/tsunagi",
9
- "version": "0.1.48",
9
+ "version": "0.1.50",
10
10
  "license": "SEE LICENSE IN LICENSE",
11
11
  "os": [
12
12
  "darwin",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minimalcorp/tsunagi",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "description": "Multi-repo GitHub project management with Claude AI integration, designed for visualizing and controlling AI-driven development locally.",
5
5
  "keywords": [
6
6
  "tsunagi",
@@ -1,3 +0,0 @@
1
- module.exports=[24361,(a,b,c)=>{b.exports=a.x("util",()=>require("util"))},84454,65486,80056,43715,a=>{"use strict";var b=a.i(30685),c=(0,a.i(17508).default)(Object.keys,Object),d=Object.prototype.hasOwnProperty;let e=function(a){if(!(0,b.default)(a))return c(a);var e=[];for(var f in Object(a))d.call(a,f)&&"constructor"!=f&&e.push(f);return e};a.s(["default",0,e],65486);var f=a.i(37991),g=a.i(11253),h=(0,f.default)(g.default,"DataView"),i=a.i(38141),j=(0,f.default)(g.default,"Promise"),k=(0,f.default)(g.default,"Set");a.s(["default",0,k],80056);var l=(0,f.default)(g.default,"WeakMap"),m=a.i(35102),n=a.i(12098),o="[object Map]",p="[object Promise]",q="[object Set]",r="[object WeakMap]",s="[object DataView]",t=(0,n.default)(h),u=(0,n.default)(i.default),v=(0,n.default)(j),w=(0,n.default)(k),x=(0,n.default)(l),y=m.default;(h&&y(new h(new ArrayBuffer(1)))!=s||i.default&&y(new i.default)!=o||j&&y(j.resolve())!=p||k&&y(new k)!=q||l&&y(new l)!=r)&&(y=function(a){var b=(0,m.default)(a),c="[object Object]"==b?a.constructor:void 0,d=c?(0,n.default)(c):"";if(d)switch(d){case t:return s;case u:return o;case v:return p;case w:return q;case x:return r}return b});let z=y;a.s(["default",0,z],43715);var A=a.i(62244),B=a.i(66723),C=a.i(68378),D=a.i(12999),E=a.i(56814),F=Object.prototype.hasOwnProperty;a.s(["default",0,function(a){if(null==a)return!0;if((0,C.default)(a)&&((0,B.default)(a)||"string"==typeof a||"function"==typeof a.splice||(0,D.default)(a)||(0,E.default)(a)||(0,A.default)(a)))return!a.length;var c=z(a);if("[object Map]"==c||"[object Set]"==c)return!a.size;if((0,b.default)(a))return!e(a).length;for(var d in a)if(F.call(a,d))return!1;return!0}],84454)},54799,(a,b,c)=>{b.exports=a.x("crypto",()=>require("crypto"))},46786,(a,b,c)=>{b.exports=a.x("os",()=>require("os"))},4446,(a,b,c)=>{b.exports=a.x("net",()=>require("net"))},73160,a=>{"use strict";var b=a.i(14562),c=a.i(34603);a.i(75930);var d=a.i(71731),e=(0,c.__name)(a=>{let{securityLevel:c}=(0,b.getConfig2)(),e=(0,d.select)("body");if("sandbox"===c){let b=(0,d.select)(`#i${a}`),c=b.node()?.contentDocument??document;e=(0,d.select)(c.body)}return e.select(`#${a}`)},"selectSvgElement");a.s(["selectSvgElement",0,e])},92025,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_katex_dist_katex_mjs_0zuygmo._.js"].map(b=>a.l(b))).then(()=>b(48986)))},69e3,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_lodash-es_0yap81y._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_dagre-KV5264BT_mjs_0aqvo3i._.js","server/chunks/ssr/node_modules_lodash-es_091xgk5._.js","server/chunks/ssr/node_modules_dagre-d3-es_src_dagre_index_097t5l0.js","server/chunks/ssr/node_modules_103v9xp._.js"].map(b=>a.l(b))).then(()=>b(55868)))},71331,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0hsalo_._.js","server/chunks/ssr/node_modules_cytoscape_dist_cytoscape_esm_mjs_0642y5z._.js"].map(b=>a.l(b))).then(()=>b(3671)))},99987,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-YZCP3GAM_mjs_04sswi2._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_c4Diagram-AHTNJAMY_mjs_0mw4ioe._.js"].map(b=>a.l(b))).then(()=>b(42357)))},48308,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_08av5m5._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_flowDiagram-DWJPFMVM_mjs_11yfm2v._.js"].map(b=>a.l(b))).then(()=>b(26594)))},74667,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_07xyphe._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_erDiagram-SMLLAGMA_mjs_0ti8x~s._.js"].map(b=>a.l(b))).then(()=>b(35543)))},15498,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_04g5ove._.js","server/chunks/ssr/[root-of-the-server]__0qtqq5d._.js","server/chunks/ssr/node_modules_0gvdioh._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_gitGraphDiagram-UUTBAWPF_mjs_0dvv8~.._.js"].map(b=>a.l(b))).then(()=>b(2421)))},24500,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0q8gl61._.js","server/chunks/ssr/node_modules_0t03q3z._.js"].map(b=>a.l(b))).then(()=>b(37521)))},78102,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0dmu3re._.js","server/chunks/ssr/[root-of-the-server]__0ff1foz._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/node_modules_0gvdioh._.js"].map(b=>a.l(b))).then(()=>b(86618)))},94433,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0zir34w._.js","server/chunks/ssr/[root-of-the-server]__0n2qong._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/node_modules_0gvdioh._.js"].map(b=>a.l(b))).then(()=>b(28018)))},65122,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0m8d9.a._.js","server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_quadrantDiagram-34T5L4WZ_mjs_05wge~v._.js"].map(b=>a.l(b))).then(()=>b(40628)))},6687,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0j1i92p._.js","server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_xychartDiagram-5P7HB3ND_mjs_0wwuvw2._.js"].map(b=>a.l(b))).then(()=>b(7451)))},18402,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_04x.vut._.js","server/chunks/ssr/0t6k_mermaid_dist_chunks_mermaid_core_requirementDiagram-MS252O5E_mjs_048lezu._.js"].map(b=>a.l(b))).then(()=>b(90431)))},92739,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_0w_54yy._.js","server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_sequenceDiagram-FGHM5R23_mjs_12c7k-5._.js"].map(b=>a.l(b))).then(()=>b(67397)))},32256,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_0o900rn._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-4TB4RGXK_mjs_0ie15wz._.js"].map(b=>a.l(b))).then(()=>b(55252)))},51050,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_03f~che._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-4TB4RGXK_mjs_0ie15wz._.js"].map(b=>a.l(b))).then(()=>b(12084)))},33430,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0mwl~df._.js","server/chunks/ssr/node_modules_lodash-es_091xgk5._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_stateDiagram-FHFEXIEX_mjs_0mg2~ri._.js","server/chunks/ssr/node_modules_dagre-d3-es_src_dagre_index_097t5l0.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-OYMX7WX6_mjs_087i3.l._.js","server/chunks/ssr/node_modules_103v9xp._.js"].map(b=>a.l(b))).then(()=>b(55905)))},43021,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_0cje6no._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-OYMX7WX6_mjs_087i3.l._.js"].map(b=>a.l(b))).then(()=>b(79891)))},21261,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0_09.d-._.js","server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_journeyDiagram-VCZTEJTY_mjs_0q7b_tk._.js"].map(b=>a.l(b))).then(()=>b(47598)))},50244,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_d3-shape_src_arc_135n374.js","server/chunks/ssr/0t6k_mermaid_dist_chunks_mermaid_core_timeline-definition-GMOUNBTQ_mjs_0y7flug._.js"].map(b=>a.l(b))).then(()=>b(98138)))},54532,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_04x.vut._.js","server/chunks/ssr/0t6k_mermaid_dist_chunks_mermaid_core_mindmap-definition-QFDTVHPH_mjs_0ie03qp._.js"].map(b=>a.l(b))).then(()=>b(73348)))},42598,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-FMBD7UC4_mjs_0dox0y0._.js","server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_kanban-definition-6JOO6SKY_mjs_0b8_92c._.js"].map(b=>a.l(b))).then(()=>b(78776)))},18652,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_d3-scale_src_0~kn3a6._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_sankeyDiagram-XADWPNL6_mjs_0akor_o._.js"].map(b=>a.l(b))).then(()=>b(88909)))},9099,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0pksdi6._.js","server/chunks/ssr/[root-of-the-server]__0hhfi7s._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/node_modules_0gvdioh._.js"].map(b=>a.l(b))).then(()=>b(20145)))},35140,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0qvxljj._.js","server/chunks/ssr/[root-of-the-server]__0hhfi7s._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/node_modules_0gvdioh._.js"].map(b=>a.l(b))).then(()=>b(42910)))},56125,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0omx0o-._.js","server/chunks/ssr/node_modules_0heie6p._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_blockDiagram-DXYQGD6D_mjs_13mbtfc._.js","server/chunks/ssr/node_modules_lodash-es_0egjqeu._.js"].map(b=>a.l(b))).then(()=>b(68669)))},54269,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0akt-n8._.js","server/chunks/ssr/[root-of-the-server]__0cl-0al._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/node_modules_0gvdioh._.js"].map(b=>a.l(b))).then(()=>b(58204)))},97375,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_076bd-f._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/[root-of-the-server]__0e2_bho._.js","server/chunks/ssr/node_modules_0gvdioh._.js","server/chunks/ssr/node_modules_0sqcrg2._.js","server/chunks/ssr/node_modules_cytoscape_dist_cytoscape_esm_mjs_0642y5z._.js"].map(b=>a.l(b))).then(()=>b(29821)))},70868,a=>{a.v(b=>Promise.all(["server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_ishikawaDiagram-UXIWVN3A_mjs_0gpauwj._.js"].map(b=>a.l(b))).then(()=>b(5822)))},5494,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_vennDiagram-DHZGUBPP_mjs_013wte~._.js"].map(b=>a.l(b))).then(()=>b(65580)))},41872,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_0bvpcr6._.js","server/chunks/ssr/[root-of-the-server]__0sha5xx._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/node_modules_0gvdioh._.js","server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_diagram-G4DWMVQ6_mjs_108p.po._.js"].map(b=>a.l(b))).then(()=>b(52172)))},40744,a=>{a.v(b=>Promise.all(["server/chunks/ssr/node_modules_076bd-f._.js","server/chunks/ssr/[root-of-the-server]__0e2_bho._.js","server/chunks/ssr/node_modules_0gvdioh._.js","server/chunks/ssr/node_modules_lodash-es_01jun1r._.js","server/chunks/ssr/0_lp_modules_mermaid_dist_chunks_mermaid_core_wardleyDiagram-NUSXRM2D_mjs_0579rrr._.js"].map(b=>a.l(b))).then(()=>b(2410)))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__00qvk7s._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[14747,(a,b,c)=>{b.exports=a.x("path",()=>require("path"))},24361,(a,b,c)=>{b.exports=a.x("util",()=>require("util"))},18622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},20635,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},24725,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},43285,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/dynamic-access-async-storage.external.js",()=>require("next/dist/server/app-render/dynamic-access-async-storage.external.js"))},11857,(a,b,c)=>{"use strict";b.exports=a.r(24951).vendored["react-rsc"].ReactServerDOMTurbopackServer},14465,(a,b,c)=>{(()=>{"use strict";var a={56:a=>{a.exports=function(a,b){return"string"==typeof a?g(a):"number"==typeof a?f(a,b):null},a.exports.format=f,a.exports.parse=g;var b=/\B(?=(\d{3})+(?!\d))/g,c=/(?:\.0*|(\.[^0]+)0+)$/,d={b:1,kb:1024,mb:1048576,gb:0x40000000,tb:0x10000000000,pb:0x4000000000000},e=/^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;function f(a,e){if(!Number.isFinite(a))return null;var f=Math.abs(a),g=e&&e.thousandsSeparator||"",h=e&&e.unitSeparator||"",i=e&&void 0!==e.decimalPlaces?e.decimalPlaces:2,j=!!(e&&e.fixedDecimals),k=e&&e.unit||"";k&&d[k.toLowerCase()]||(k=f>=d.pb?"PB":f>=d.tb?"TB":f>=d.gb?"GB":f>=d.mb?"MB":f>=d.kb?"KB":"B");var l=(a/d[k.toLowerCase()]).toFixed(i);return j||(l=l.replace(c,"$1")),g&&(l=l.split(".").map(function(a,c){return 0===c?a.replace(b,g):a}).join(".")),l+h+k}function g(a){if("number"==typeof a&&!isNaN(a))return a;if("string"!=typeof a)return null;var b,c=e.exec(a),f="b";return c?(b=parseFloat(c[1]),f=c[4].toLowerCase()):(b=parseInt(a,10),f="b"),Math.floor(d[f]*b)}}},c={};function d(b){var e=c[b];if(void 0!==e)return e.exports;var f=c[b]={exports:{}},g=!0;try{a[b](f,f.exports,d),g=!1}finally{g&&delete c[b]}return f.exports}d.ab="/ROOT/node_modules/next/dist/compiled/bytes/",b.exports=d(56)})()},20460,(a,b,c)=>{(()=>{"use strict";"u">typeof __nccwpck_require__&&(__nccwpck_require__.ab="/ROOT/node_modules/next/dist/compiled/cookie/");var a,c,d,e,f={};f.parse=function(b,c){if("string"!=typeof b)throw TypeError("argument str must be a string");for(var e={},f=b.split(d),g=(c||{}).decode||a,h=0;h<f.length;h++){var i=f[h],j=i.indexOf("=");if(!(j<0)){var k=i.substr(0,j).trim(),l=i.substr(++j,i.length).trim();'"'==l[0]&&(l=l.slice(1,-1)),void 0==e[k]&&(e[k]=function(a,b){try{return b(a)}catch(b){return a}}(l,g))}}return e},f.serialize=function(a,b,d){var f=d||{},g=f.encode||c;if("function"!=typeof g)throw TypeError("option encode is invalid");if(!e.test(a))throw TypeError("argument name is invalid");var h=g(b);if(h&&!e.test(h))throw TypeError("argument val is invalid");var i=a+"="+h;if(null!=f.maxAge){var j=f.maxAge-0;if(isNaN(j)||!isFinite(j))throw TypeError("option maxAge is invalid");i+="; Max-Age="+Math.floor(j)}if(f.domain){if(!e.test(f.domain))throw TypeError("option domain is invalid");i+="; Domain="+f.domain}if(f.path){if(!e.test(f.path))throw TypeError("option path is invalid");i+="; Path="+f.path}if(f.expires){if("function"!=typeof f.expires.toUTCString)throw TypeError("option expires is invalid");i+="; Expires="+f.expires.toUTCString()}if(f.httpOnly&&(i+="; HttpOnly"),f.secure&&(i+="; Secure"),f.sameSite)switch("string"==typeof f.sameSite?f.sameSite.toLowerCase():f.sameSite){case!0:case"strict":i+="; SameSite=Strict";break;case"lax":i+="; SameSite=Lax";break;case"none":i+="; SameSite=None";break;default:throw TypeError("option sameSite is invalid")}return i},a=decodeURIComponent,c=encodeURIComponent,d=/; */,e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/,b.exports=f})()},70406,(a,b,c)=>{b.exports=a.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},24951,(a,b,c)=>{"use strict";b.exports=a.r(18622)},7997,(a,b,c)=>{"use strict";b.exports=a.r(24951).vendored["react-rsc"].ReactJsxRuntime},717,(a,b,c)=>{"use strict";b.exports=a.r(24951).vendored["react-rsc"].React}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0a8.h72._.js.map