feat: add multi-channel support and language filtering to focus on specific speakers
This commit is contained in:
@@ -65,6 +65,10 @@ Run the script using `python3 transcribe.py` with optional flags.
|
|||||||
- `-c`, `--context`: Enable prompt caching/rolling context to help the model maintain sentence continuity across chunks.
|
- `-c`, `--context`: Enable prompt caching/rolling context to help the model maintain sentence continuity across chunks.
|
||||||
- `--lang [CODE]`: Hardcode the source language (e.g., `en`, `es`) to bypass automatic language detection for faster processing.
|
- `--lang [CODE]`: Hardcode the source language (e.g., `en`, `es`) to bypass automatic language detection for faster processing.
|
||||||
- `--silence [MS]`: Set the minimum silence duration in milliseconds to end a chunk. Defaults to 1000ms. Increase to force longer sentences before translation.
|
- `--silence [MS]`: Set the minimum silence duration in milliseconds to end a chunk. Defaults to 1000ms. Increase to force longer sentences before translation.
|
||||||
|
- `--max-buffer [SEC]`: Maximum buffer duration in seconds before forcing a flush (default: 20).
|
||||||
|
- `--channels [N]`: Number of input channels (default: 1).
|
||||||
|
- `--pick-channel [0|1]`: If stereo, select channel 0 (Left) or 1 (Right) to focus transcription.
|
||||||
|
- `--filter-lang`: If used with `--lang`, discards segments that do not match the target language.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+21
-3
@@ -43,7 +43,6 @@ TARGET_LANGS = {
|
|||||||
"ar": "Helsinki-NLP/opus-mt-en-ar" # Added Arabic as discussed before
|
"ar": "Helsinki-NLP/opus-mt-en-ar" # Added Arabic as discussed before
|
||||||
}
|
}
|
||||||
|
|
||||||
CHANNELS = 1
|
|
||||||
SAMPLERATE = 16000
|
SAMPLERATE = 16000
|
||||||
BLOCK_SIZE = 512
|
BLOCK_SIZE = 512
|
||||||
VAD_THRESHOLD = 0.5
|
VAD_THRESHOLD = 0.5
|
||||||
@@ -127,6 +126,9 @@ def main():
|
|||||||
parser.add_argument("--lang", type=str, help="Hardcode source language (e.g. 'en', 'es') to bypass detection")
|
parser.add_argument("--lang", type=str, help="Hardcode source language (e.g. 'en', 'es') to bypass detection")
|
||||||
parser.add_argument("--silence", type=int, default=1000, help="Minimum silence duration in ms to end a chunk (default: 1000)")
|
parser.add_argument("--silence", type=int, default=1000, help="Minimum silence duration in ms to end a chunk (default: 1000)")
|
||||||
parser.add_argument("--max-buffer", type=int, default=20, help="Maximum buffer duration in seconds before forcing a flush (default: 20)")
|
parser.add_argument("--max-buffer", type=int, default=20, help="Maximum buffer duration in seconds before forcing a flush (default: 20)")
|
||||||
|
parser.add_argument("--channels", type=int, default=1, help="Number of input channels (default: 1)")
|
||||||
|
parser.add_argument("--pick-channel", type=int, choices=[0, 1], help="Pick a specific channel (0 or 1) from stereo input")
|
||||||
|
parser.add_argument("--filter-lang", action="store_true", help="Discard segments where detected language does not match --lang")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -210,10 +212,17 @@ def main():
|
|||||||
last_draft_text = ""
|
last_draft_text = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with sd.InputStream(samplerate=SAMPLERATE, channels=CHANNELS, callback=callback, blocksize=BLOCK_SIZE, device=device_index):
|
with sd.InputStream(samplerate=SAMPLERATE, channels=args.channels, callback=callback, blocksize=BLOCK_SIZE, device=device_index):
|
||||||
while True:
|
while True:
|
||||||
while not audio_queue.empty():
|
while not audio_queue.empty():
|
||||||
data = audio_queue.get()
|
data = audio_queue.get()
|
||||||
|
if args.channels > 1:
|
||||||
|
if args.pick_channel is not None:
|
||||||
|
# Select specific channel
|
||||||
|
data = data[:, args.pick_channel]
|
||||||
|
else:
|
||||||
|
# Mix to mono
|
||||||
|
data = np.mean(data, axis=1)
|
||||||
audio_buffer.append(data.flatten())
|
audio_buffer.append(data.flatten())
|
||||||
|
|
||||||
if len(audio_buffer) > 0:
|
if len(audio_buffer) > 0:
|
||||||
@@ -269,6 +278,11 @@ def main():
|
|||||||
original_text = transcription_result['text'].strip()
|
original_text = transcription_result['text'].strip()
|
||||||
detected_lang = transcription_result.get('language', args.lang if args.lang else 'en')
|
detected_lang = transcription_result.get('language', args.lang if args.lang else 'en')
|
||||||
|
|
||||||
|
# Filter language if requested
|
||||||
|
if args.filter_lang and args.lang and detected_lang != args.lang:
|
||||||
|
print(f"\n[SYSTEM]: Discarding segment (Detected: {detected_lang}, Expected: {args.lang})")
|
||||||
|
original_text = ""
|
||||||
|
|
||||||
if is_hallucination(original_text):
|
if is_hallucination(original_text):
|
||||||
print(f"\n[SYSTEM]: Hallucination detected, ignoring and resetting context.")
|
print(f"\n[SYSTEM]: Hallucination detected, ignoring and resetting context.")
|
||||||
original_text = ""
|
original_text = ""
|
||||||
@@ -344,7 +358,11 @@ def main():
|
|||||||
|
|
||||||
draft_result = mlx_whisper.transcribe(current_audio, **draft_kwargs)
|
draft_result = mlx_whisper.transcribe(current_audio, **draft_kwargs)
|
||||||
draft_text = draft_result['text'].strip()
|
draft_text = draft_result['text'].strip()
|
||||||
|
draft_lang = draft_result.get('language', args.lang if args.lang else 'en')
|
||||||
|
|
||||||
|
if args.filter_lang and args.lang and draft_lang != args.lang:
|
||||||
|
draft_text = ""
|
||||||
|
|
||||||
if draft_text:
|
if draft_text:
|
||||||
# Update timestamp ONLY if the text actually changed
|
# Update timestamp ONLY if the text actually changed
|
||||||
if draft_text != last_draft_text:
|
if draft_text != last_draft_text:
|
||||||
|
|||||||
Reference in New Issue
Block a user