feat: upload audio, get a private Swedish transcript, discuss it (#33, ADR-033) #39
@@ -121,7 +121,7 @@ func TestGateway_NormalisesTheVerboseJSONResponse(t *testing.T) {
|
||||
got, err := g.Transcribe(context.Background(), wavFile(t, "x"))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "God morgon allihopa.\n Vi går igenom läget.", got.Text)
|
||||
assert.Equal(t, "God morgon allihopa. Vi går igenom läget.", got.Text)
|
||||
assert.Equal(t, "iguana/kb-whisper", got.Endpoint, "the serving endpoint is part of the result")
|
||||
assert.InDelta(t, 4.25, got.AudioSeconds, 1e-9)
|
||||
assert.Equal(t, []domain.Segment{
|
||||
@@ -172,3 +172,61 @@ func TestGateway_MissingAudioFileIsAnError(t *testing.T) {
|
||||
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
// whisper.cpp wraps its output at ~60 characters, and a wrap can land INSIDE a word:
|
||||
// the continuation segment has no leading space, the `text` field joins segments
|
||||
// with newlines, and a segment can be a lone ".". Measured on real gateway output
|
||||
// 2026-10-01: 7% of a one-hour recording's segments were such fragments. Joining by
|
||||
// newline hands the chat model broken words ("nyt\nt"), so Text is rebuilt from the
|
||||
// segments: a segment that begins with a space starts a new word, one that does not
|
||||
// continues the previous one.
|
||||
func TestGateway_RejoinsWordsWhisperCppSplitAcrossSegments(t *testing.T) {
|
||||
reply := `{
|
||||
"text": " Vi ligger just nu 12 procent över den ursprungliga kalkylen\n.\n Det kräver ett nyt\nt godkännande från beställaren.\n Framförallt på arbetspl\natsen.\n",
|
||||
"language": "swedish", "duration": 20,
|
||||
"segments": [
|
||||
{"start": 0, "end": 4, "text": " Vi ligger just nu 12 procent över den ursprungliga kalkylen"},
|
||||
{"start": 4, "end": 5, "text": "."},
|
||||
{"start": 5, "end": 8, "text": " Det kräver ett nyt"},
|
||||
{"start": 8, "end": 11, "text": "t godkännande från beställaren."},
|
||||
{"start": 11, "end": 14, "text": " Framförallt på arbetspl"},
|
||||
{"start": 14, "end": 16, "text": "atsen."}
|
||||
]}`
|
||||
srv := serve(t, 200, reply, nil)
|
||||
g := transcribe.NewGateway(srv.URL+"/v1", "k", "iguana/kb-whisper", srv.Client())
|
||||
|
||||
got, err := g.Transcribe(context.Background(), wavFile(t, "x"))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Vi ligger just nu 12 procent över den ursprungliga kalkylen. "+
|
||||
"Det kräver ett nytt godkännande från beställaren. Framförallt på arbetsplatsen.", got.Text)
|
||||
assert.Len(t, got.Segments, 6, "the timed segments are kept as the backend gave them (trimmed)")
|
||||
assert.Equal(t, ".", got.Segments[1].Text)
|
||||
}
|
||||
|
||||
func TestGateway_SentenceLevelSegmentsWithNoLeadingSpaceAreJoinedWithASpace(t *testing.T) {
|
||||
// berget/kb-whisper returns whole sentences with no leading space; rebuilding by
|
||||
// concatenation would glue them ("allihopa!Vi").
|
||||
reply := `{"text": "God morgon allihopa!\nVi går igenom läget.", "language": "sv", "duration": 5,
|
||||
"segments": [
|
||||
{"start": 0.05, "end": 1.2, "text": "God morgon allihopa!"},
|
||||
{"start": 1.6, "end": 4.2, "text": "Vi går igenom läget."}
|
||||
]}`
|
||||
srv := serve(t, 200, reply, nil)
|
||||
g := transcribe.NewGateway(srv.URL+"/v1", "k", "berget/kb-whisper", srv.Client())
|
||||
|
||||
got, err := g.Transcribe(context.Background(), wavFile(t, "x"))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "God morgon allihopa! Vi går igenom läget.", got.Text)
|
||||
}
|
||||
|
||||
func TestGateway_WithNoSegmentsTheTextFieldIsUsedWithWhitespaceCollapsed(t *testing.T) {
|
||||
srv := serve(t, 200, `{"text": " Hej allihopa.\n Vi börjar. ", "duration": 3, "segments": []}`, nil)
|
||||
g := transcribe.NewGateway(srv.URL+"/v1", "k", "m", srv.Client())
|
||||
|
||||
got, err := g.Transcribe(context.Background(), wavFile(t, "x"))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Hej allihopa. Vi börjar.", got.Text)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user