@@ -190,14 +190,15 @@ original_live_transcription() {
190190 trap cleanup SIGINT SIGTERM
191191
192192 # Incremental chunk-based live transcription
193- # rec writes 16kHz mono 16-bit PCM = 32000 bytes/sec
194- # WAV header is not finalized until rec stops, so we calculate
195- # duration from file size and extract raw PCM bytes directly.
193+ # rec writes 16kHz mono 16-bit PCM = 32000 bytes/sec.
194+ # The WAV header is NOT finalized until rec stops, so we:
195+ # 1. Estimate duration from file size
196+ # 2. Tell sox to read the file as raw PCM (-t raw), bypassing the broken header
197+ # 3. Use sox trim to extract time ranges directly
196198 local BYTES_PER_SEC=32000
197- local WAV_HEADER_SIZE=44
198199 local MIN_CHUNK_SECS=10
199200 local OVERLAP_SECS=2
200- local last_byte_offset= $WAV_HEADER_SIZE
201+ local last_secs=0
201202 local chunk_count=0
202203 local running_transcript=" /tmp/running_transcript_${TIMESTAMP} .txt"
203204 touch " $running_transcript "
@@ -206,29 +207,26 @@ original_live_transcription() {
206207 if [ -f " $recording_file " ]; then
207208 local current_size
208209 current_size=$( stat -f%z " $recording_file " 2> /dev/null || echo " 0" )
209- local new_bytes =$(( current_size - last_byte_offset ))
210- local new_secs=$(( new_bytes / BYTES_PER_SEC ))
210+ local current_secs =$(( current_size / BYTES_PER_SEC ))
211+ local new_secs=$(( current_secs - last_secs ))
211212
212213 if [ " $new_secs " -ge " $MIN_CHUNK_SECS " ]; then
213214 chunk_count=$(( chunk_count + 1 ))
214215
215- # Include overlap from previous chunk for context (except first chunk)
216- local overlap_bytes=0
217- if [ " $chunk_count " -gt 1 ]; then
218- overlap_bytes=$(( OVERLAP_SECS * BYTES_PER_SEC))
219- fi
220- local extract_offset=$(( last_byte_offset - overlap_bytes))
221- local chunk_bytes=$(( new_secs * BYTES_PER_SEC + overlap_bytes))
222-
223- local raw_file=" /tmp/chunk_raw_${TIMESTAMP} _${chunk_count} .pcm"
224216 local chunk_file=" /tmp/chunk_${TIMESTAMP} _${chunk_count} .wav"
225217
226- # Extract raw PCM bytes (bypass incomplete WAV header)
227- dd if=" $recording_file " of=" $raw_file " bs=1 skip=" $extract_offset " count=" $chunk_bytes " 2> /dev/null
218+ # Include overlap from previous chunk for context (except first chunk)
219+ local trim_start=$last_secs
220+ if [ " $chunk_count " -gt 1 ] && [ " $trim_start " -ge " $OVERLAP_SECS " ]; then
221+ trim_start=$(( trim_start - OVERLAP_SECS))
222+ fi
223+ local trim_duration=$(( current_secs - trim_start))
228224
229- # Convert raw PCM to valid WAV for whisper-cli
230- sox -t raw -r 16000 -c 1 -b 16 -e signed-integer -L " $raw_file " " $chunk_file " 2> /dev/null
231- rm -f " $raw_file "
225+ # Read recording as raw PCM (bypasses unfinalised WAV header)
226+ # and extract only the time range we need
227+ sox -t raw -r 16000 -c 1 -b 16 -e signed-integer -L \
228+ " $recording_file " " $chunk_file " \
229+ trim " $trim_start " " $trim_duration " 2> /dev/null
232230
233231 if [ -f " $chunk_file " ] && [ -s " $chunk_file " ]; then
234232 local chunk_transcript=" /tmp/chunk_transcript_${TIMESTAMP} _${chunk_count} "
@@ -241,7 +239,7 @@ original_live_transcription() {
241239 new_text=$( cat " ${chunk_transcript} .txt" | sed ' /^$/d' )
242240 # Filter out Whisper hallucinations on silence/noise
243241 local filtered_text
244- filtered_text=$( echo " $new_text " | grep -viE ' ^\[.*\]$|^\*.*\ *$|^[[:space:]]*$' || true)
242+ filtered_text=$( echo " $new_text " | grep -viE ' ^\s*[\[\(\*].*[\]\)\*]\s *$|^[[:space:]]*$' || true)
245243 if [ -n " $filtered_text " ]; then
246244 echo " $filtered_text " >> " $running_transcript "
247245 print_color " $GREEN " " $filtered_text " >&2
@@ -251,8 +249,7 @@ original_live_transcription() {
251249 rm -f " $chunk_file " " ${chunk_transcript} .txt" 2> /dev/null
252250 fi
253251
254- # Advance position (without overlap — overlap is re-read next time)
255- last_byte_offset=$(( last_byte_offset + new_secs * BYTES_PER_SEC))
252+ last_secs=$current_secs
256253 fi
257254 fi
258255 sleep 2
0 commit comments