@@ -3,8 +3,8 @@ import { createReadableStreamFromReadable } from '@react-router/node'
33import {
44 getAudioBuffer ,
55 getAudioStream ,
6+ headAudioObject ,
67 parseHttpByteRangeHeader ,
7- parseBase64DataUrl ,
88} from '#app/utils/call-kent-audio-storage.server.ts'
99import { prisma } from '#app/utils/prisma.server.ts'
1010import { requireUser } from '#app/utils/session.server.ts'
@@ -23,25 +23,42 @@ export async function loader({ request }: Route.LoaderArgs) {
2323 audioKey : true ,
2424 audioContentType : true ,
2525 audioSize : true ,
26- base64 : true , // legacy fallback
2726 } ,
2827 } )
2928 if ( ! call ) throw new Response ( 'Not found' , { status : 404 } )
29+ if ( ! call . audioKey ) throw new Response ( 'Not found' , { status : 404 } )
3030
31+ const audioKey = call . audioKey
3132 let contentType = call . audioContentType ?? 'application/octet-stream'
3233 let size = call . audioSize ?? null
3334
3435 const rangeHeader = request . headers . get ( 'range' )
35- if ( call . audioKey ) {
36- // R2-backed
37- if ( typeof size !== 'number' || ! Number . isFinite ( size ) || size <= 0 ) {
38- // Size should always be present for R2-backed audio; keep a safe fallback.
39- const buffer = await getAudioBuffer ( { key : call . audioKey ! } )
36+ // R2-backed (or mock implementation when running locally with mocks).
37+ if ( typeof size !== 'number' || ! Number . isFinite ( size ) || size <= 0 ) {
38+ // Size should always be present for stored audio. Prefer HEAD metadata over
39+ // buffering the entire object.
40+ try {
41+ const head = await headAudioObject ( { key : audioKey } )
42+ size = head . size
43+ if ( contentType === 'application/octet-stream' && head . contentType ) {
44+ contentType = head . contentType
45+ }
46+ console . warn (
47+ `call-audio: missing/invalid audioSize for callId=${ callId } audioKey=${ audioKey } resolvedSize=${ size } source=head` ,
48+ )
49+ } catch {
50+ // Fall back to buffering only if HEAD fails for some reason.
51+ const buffer = await getAudioBuffer ( { key : audioKey } )
4052 size = buffer . byteLength
53+ console . warn (
54+ `call-audio: missing/invalid audioSize for callId=${ callId } audioKey=${ audioKey } resolvedSize=${ size } source=buffer` ,
55+ )
4156 const range = rangeHeader
4257 ? parseHttpByteRangeHeader ( rangeHeader , size )
4358 : null
44- const body = range ? buffer . subarray ( range . start , range . end + 1 ) : buffer
59+ const body = range
60+ ? buffer . subarray ( range . start , range . end + 1 )
61+ : buffer
4562 const stream = Readable . from ( body )
4663 return new Response ( createReadableStreamFromReadable ( stream ) , {
4764 status : range ? 206 : 200 ,
@@ -58,41 +75,14 @@ export async function loader({ request }: Route.LoaderArgs) {
5875 } ,
5976 } )
6077 }
61-
62- const range = rangeHeader
63- ? parseHttpByteRangeHeader ( rangeHeader , size )
64- : null
65- const { body } = await getAudioStream ( {
66- key : call . audioKey ,
67- range : range ?? undefined ,
68- } )
69- return new Response ( createReadableStreamFromReadable ( body ) , {
70- status : range ? 206 : 200 ,
71- headers : {
72- 'Content-Type' : contentType ,
73- 'Accept-Ranges' : 'bytes' ,
74- ...( range
75- ? {
76- 'Content-Range' : `bytes ${ range . start } -${ range . end } /${ size } ` ,
77- 'Content-Length' : String ( range . end - range . start + 1 ) ,
78- }
79- : { 'Content-Length' : String ( size ) } ) ,
80- 'Cache-Control' : 'private, max-age=3600' ,
81- } ,
82- } )
8378 }
8479
85- // Legacy DB-backed base64 audio
86- if ( ! call . base64 ) throw new Response ( 'Not found' , { status : 404 } )
87- const parsed = parseBase64DataUrl ( call . base64 )
88- contentType = parsed . contentType
89- size = parsed . buffer . byteLength
9080 const range = rangeHeader ? parseHttpByteRangeHeader ( rangeHeader , size ) : null
91- const body = range
92- ? parsed . buffer . subarray ( range . start , range . end + 1 )
93- : parsed . buffer
94- const stream = Readable . from ( body )
95- return new Response ( createReadableStreamFromReadable ( stream ) , {
81+ const { body } = await getAudioStream ( {
82+ key : audioKey ,
83+ range : range ?? undefined ,
84+ } )
85+ return new Response ( createReadableStreamFromReadable ( body ) , {
9686 status : range ? 206 : 200 ,
9787 headers : {
9888 'Content-Type' : contentType ,
0 commit comments