feat: Apple Speech v3 + Freeflow polish + draft streaming
- Apple SpeechAnalyzer (macOS 26+) binary: --bench (31x RTF), --pipe
(persistent process, 150ms finals), --live (word-by-word drafts)
- Pipe protocol: 4-byte BE length + wav payload, emits JSONL
{event:draft|final, text, isFinal, chunk} — 31 drafts for 6s audio (~60ms granularity)
- engine_apple_transcribe.py: ApplePipeTranscriber with
transcribe() + transcribe_with_draft_callback(), VAD + draft
queue, new flags --apple-stream (on), --apple-stream-interval,
--apple-pipe (on). Fixes PIL/transformers import crash by lazy import.
- main_v3.py: engine selector {whisper,apple}, passthrough translate
when no -es/-fr/-ar, freeflow flags same as v2
- Freeflow polish: deterministic punctuation commands (comma,
question mark, new paragraph, at sign), filler stripping,
<keep> protection, skip-clean heuristic, freeflow/qwen/legacy
prompt styles. Much better final readability vs raw Apple/Whisper.
- main_v2.py, engine_llm.py, engine_distribute.py: integrate freeflow
- bench: Apple 2.12% WER vs Whisper Small 3.74% (Inscribe), CPU
0mW ANE (measured via powermetrics), 196M EN cryptex per locale.
- Verified: 31 word-by-word drafts, 2 finals, exit 0, bench regression ok.
Freeflow still much better for final polish — Apple wins on speed
and raw accuracy, freeflow wins on readable paragraph output.
Co-authored-by: internal-model
This commit is contained in:
@@ -401,6 +401,73 @@ Decision rules:
|
||||
"""
|
||||
variants.append((f"grounded_ctx{window_size}_no_prev_source", system_ctx, user_ctx_no_prev_source))
|
||||
|
||||
if window_size == 2:
|
||||
system_ctx_paragraph = """You are a careful live transcript editor working from noisy translated source text.
|
||||
|
||||
Goal:
|
||||
Produce faithful, readable English paragraphs.
|
||||
|
||||
Decision rules:
|
||||
1. NEW SOURCE TEXT is the primary evidence and should dominate the output.
|
||||
2. Use PREVIOUS SOURCE TEXT and PREVIOUS REFINED CONTEXT only when they clearly help resolve or continue the new material.
|
||||
3. The final answer must be English only.
|
||||
4. Never copy non-English words into the output unless they are proper names.
|
||||
5. If a non-English fragment appears as an isolated clause, trailing fragment, or side comment without a clear English anchor, drop it.
|
||||
6. Only translate a non-English fragment when it is clearly central to the same idea and its meaning is reasonably obvious from context.
|
||||
7. If NEW SOURCE TEXT continues the same thought as PREVIOUS REFINED CONTEXT, merge them into one coherent paragraph.
|
||||
8. If NEW SOURCE TEXT starts a fresh thought, start a new paragraph instead of forcing a merge.
|
||||
9. Remove exact or near-exact repetition unless the repetition is clearly intentional rhetoric.
|
||||
10. Make obvious caption-word mistakes make sense only when the intended English wording is reasonably clear from context.
|
||||
11. Prefer conservative wording over guessed meaning.
|
||||
12. Use a double newline between distinct paragraphs.
|
||||
13. Do not add explanations, disclaimers, labels, or meta commentary.
|
||||
14. Return only the revised paragraph text."""
|
||||
user_ctx_paragraph = f"""Synthesize the transcript into coherent paragraphs.
|
||||
|
||||
[PREVIOUS REFINED CONTEXT]
|
||||
{context_window}
|
||||
|
||||
[PREVIOUS SOURCE TEXT]
|
||||
"{prev_raw}"
|
||||
|
||||
[NEW SOURCE TEXT]
|
||||
"{new_raw}"
|
||||
"""
|
||||
variants.append(("grounded_ctx2_paragraph_live", system_ctx_paragraph, user_ctx_paragraph))
|
||||
|
||||
system_ctx_paragraph_soft = """You are a careful live transcript editor working from noisy translated source text.
|
||||
|
||||
Goal:
|
||||
Produce the most faithful readable English update.
|
||||
|
||||
Decision rules:
|
||||
1. NEW SOURCE TEXT is the primary evidence and should dominate the output.
|
||||
2. Use PREVIOUS SOURCE TEXT and PREVIOUS REFINED CONTEXT only when they clearly help resolve or continue the new material.
|
||||
3. The final answer must be English only.
|
||||
4. Never copy non-English words into the output unless they are proper names.
|
||||
5. If a non-English fragment appears as an isolated clause, trailing fragment, or side comment without a clear English anchor, drop it.
|
||||
6. Only translate a non-English fragment when it is clearly central to the same idea and its meaning is reasonably obvious from context.
|
||||
7. If NEW SOURCE TEXT clearly continues PREVIOUS REFINED CONTEXT, you may merge them naturally.
|
||||
8. If NEW SOURCE TEXT starts a fresh thought, output only the new material and do not drag older context forward.
|
||||
9. If both pieces are relevant but distinct adjacent thoughts, separate them with a double newline.
|
||||
10. Remove exact or near-exact repetition unless the repetition is clearly intentional rhetoric.
|
||||
11. Make obvious caption-word mistakes make sense only when the intended English wording is reasonably clear from context.
|
||||
12. Prefer conservative wording over guessed meaning.
|
||||
13. Do not add explanations, disclaimers, labels, or meta commentary.
|
||||
14. Return only the revised transcript text."""
|
||||
user_ctx_paragraph_soft = f"""Edit this transcript update as readable paragraph text.
|
||||
|
||||
[PREVIOUS REFINED CONTEXT]
|
||||
{context_window}
|
||||
|
||||
[PREVIOUS SOURCE TEXT]
|
||||
"{prev_raw}"
|
||||
|
||||
[NEW SOURCE TEXT]
|
||||
"{new_raw}"
|
||||
"""
|
||||
variants.append(("grounded_ctx2_paragraph_soft", system_ctx_paragraph_soft, user_ctx_paragraph_soft))
|
||||
|
||||
system_ctx_repair = """You are a careful live transcript editor working from noisy translated source text.
|
||||
|
||||
Goal:
|
||||
|
||||
Reference in New Issue
Block a user