From b772cb57b2b8362adb2b2e29dddbd77b03cd8267 Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Wed, 25 Sep 2024 10:39:27 +0200 Subject: [PATCH] backend: Improved the recording streaming Send chunks instead of entire file allowing release the file when stop playing --- backend/src/controllers/recording.controller.ts | 5 ++--- backend/src/services/recording.service.ts | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/recording.controller.ts b/backend/src/controllers/recording.controller.ts index 05924d3d..5fffbf95 100644 --- a/backend/src/controllers/recording.controller.ts +++ b/backend/src/controllers/recording.controller.ts @@ -85,8 +85,6 @@ export const streamRecording = async (req: Request, res: Response) => { logger.info(`Streaming recording ${recordingId}`); const { fileSize, fileStream, start, end } = await recordingService.getRecordingAsStream(recordingId, range); - res.setHeader('Accept-Ranges', 'bytes'); - if (range && fileSize && start !== undefined && end !== undefined) { const contentLength = end - start + 1; @@ -94,7 +92,7 @@ export const streamRecording = async (req: Request, res: Response) => { 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 'Accept-Ranges': 'bytes', 'Content-Length': contentLength, - 'Content-Type': 'video/webm' + 'Content-Type': 'video/mp4' }); fileStream.on('error', (streamError) => { @@ -104,6 +102,7 @@ export const streamRecording = async (req: Request, res: Response) => { fileStream.pipe(res).on('finish', () => res.end()); } else { + res.setHeader('Accept-Ranges', 'bytes'); res.setHeader('Content-Type', 'video/mp4'); if (fileSize) res.setHeader('Content-Length', fileSize); diff --git a/backend/src/services/recording.service.ts b/backend/src/services/recording.service.ts index d0705c47..a0f70882 100644 --- a/backend/src/services/recording.service.ts +++ b/backend/src/services/recording.service.ts @@ -206,6 +206,7 @@ export class RecordingService { recordingId: string, range?: string ): Promise<{ fileSize: number | undefined; fileStream: Readable; start?: number; end?: number }> { + const RECORDING_FILE_PORTION_SIZE = 5 * 1024 * 1024; // 5MB const egressInfo = await this.getRecording(recordingId); const recordingPath = RecordingHelper.extractFileNameFromUrl(egressInfo.location); @@ -218,7 +219,8 @@ export class RecordingService { // Parse the range header const parts = range.replace(/bytes=/, '').split('-'); const start = parseInt(parts[0], 10); - const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1; + const endRange = parts[1] ? parseInt(parts[1], 10) : start + RECORDING_FILE_PORTION_SIZE; + const end = Math.min(endRange, fileSize - 1); const fileStream = await this.s3Service.getObjectAsStream(recordingPath, CALL_S3_BUCKET, { start, end