Skip to content

Instantly share code, notes, and snippets.

@abe238
Last active August 23, 2026 06:55
Show Gist options
  • Select an option

  • Save abe238/baa86c6692a2175897d080bb4bb1aa85 to your computer and use it in GitHub Desktop.

Select an option

Save abe238/baa86c6692a2175897d080bb4bb1aa85 to your computer and use it in GitHub Desktop.
canary-180m-flash empty-transcript reproduction (transcribe.cpp)

canary-180m-flash empty-transcript reproduction

Companion files for an issue on handy-computer/transcribe.cpp.

file canary-180m-flash Apple Speech, same bytes
empty-golden-anchor.wav (7.5s) 0 chars, status 0, 0.05s "Golden Anchor 99, recorder path guard verified."
empty-crimson-falcon.wav (7.3s) 0 chars, status 0, 0.04s "Crimson Falcon 42. Single install verified."
ok-same-mic-control.wav (6s) 55 chars ✓

All 16 kHz mono. All machine-generated: macOS say played through the laptop speakers and recorded by the built-in mic. No human speech.

ok-same-mic-control.wav was recorded minutes later through the same mic, same room, same speaker-playback path, and transcribes correctly — so the failures are not a capture-quality problem.

probe.c links the xcframework and calls transcribe_run directly, with no application code:

clang -O2 -o probe probe.c -I <fw>/CTranscribe.framework/Headers \
    -F <fw> -framework CTranscribe -Wl,-rpath,<fw>
./probe canary-180m-flash-Q8_0.gguf empty-golden-anchor.wav empty-crimson-falcon.wav ok-same-mic-control.wav
#include <transcribe.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
// Minimal 16-bit mono WAV reader: walk chunks to find "data".
static float *read_wav(const char *path, int *out_n) {
FILE *f = fopen(path, "rb"); if (!f) return NULL;
char id[4]; uint32_t sz;
fseek(f, 12, SEEK_SET); // skip RIFF/WAVE
while (fread(id, 1, 4, f) == 4 && fread(&sz, 4, 1, f) == 1) {
if (!memcmp(id, "data", 4)) {
int n = sz / 2;
int16_t *pcm = malloc(sz);
if (fread(pcm, 1, sz, f) != sz) { free(pcm); fclose(f); return NULL; }
float *out = malloc(sizeof(float) * n);
for (int i = 0; i < n; i++) out[i] = pcm[i] / 32768.0f; // same as CanaryEngine.normalize
free(pcm); fclose(f); *out_n = n; return out;
}
fseek(f, (sz + 1) & ~1u, SEEK_CUR);
}
fclose(f); return NULL;
}
int main(int argc, char **argv) {
if (argc < 3) { fprintf(stderr, "usage: probe <model.gguf> <wav>...\n"); return 2; }
struct transcribe_model_load_params mp;
transcribe_model_load_params_init(&mp); // device left unset = automatic (v0.2 change)
struct transcribe_model *model = NULL;
transcribe_status st = transcribe_model_load_file(argv[1], &mp, &model);
if ((int)st != 0 || !model) { fprintf(stderr, "model load failed: %d\n", (int)st); return 1; }
printf("loaded transcribe.cpp %s\n", TRANSCRIBE_VERSION);
for (int a = 2; a < argc; a++) {
int n = 0; float *pcm = read_wav(argv[a], &n);
if (!pcm) { printf("%-34s WAV READ FAILED\n", argv[a]); continue; }
struct transcribe_session_params sp; transcribe_session_params_init(&sp);
struct transcribe_session *sess = NULL;
if ((int)transcribe_session_init(model, &sp, &sess) != 0 || !sess) {
printf("%-34s SESSION FAILED\n", argv[a]); free(pcm); continue;
}
struct transcribe_run_params rp; transcribe_run_params_init(&rp);
rp.language = "en"; rp.target_language = "en"; // same as Warbler
struct timespec t0, t1; clock_gettime(CLOCK_MONOTONIC, &t0);
transcribe_status rs = transcribe_run(sess, pcm, n, &rp);
clock_gettime(CLOCK_MONOTONIC, &t1);
double dt = (t1.tv_sec - t0.tv_sec) + (t1.tv_nsec - t0.tv_nsec) / 1e9;
const char *txt = ((int)rs == 0) ? transcribe_full_text(sess) : NULL;
const char *base = strrchr(argv[a], '/'); base = base ? base + 1 : argv[a];
printf("%-34s %5.2fs status=%d chars=%zu %s\n", base, dt, (int)rs,
txt ? strlen(txt) : 0,
(txt && *txt) ? txt : "<<< EMPTY >>>");
transcribe_session_free(sess); free(pcm);
}
transcribe_model_free(model);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment