feat: enhance streaming functionality with format support and fallback mechanism
- Added support for an optional 'format' query parameter in the streaming endpoint to allow raw file retrieval. - Implemented a fallback mechanism in the VideoPlayer to automatically switch to raw file playback when HLS streaming fails. - Improved error handling and logging for HLS playback issues, ensuring better user feedback and recovery attempts. - Updated the Indeehub API service to accommodate the new format parameter in the streaming URL request.
This commit is contained in:
@@ -80,6 +80,7 @@ export class ContentsController {
|
||||
@UseGuards(OptionalHybridAuthGuard)
|
||||
async stream(
|
||||
@Param('id') id: string,
|
||||
@Query('format') format: string,
|
||||
@Req() req: any,
|
||||
) {
|
||||
// Try content ID first; if not found, try looking up project to find its content
|
||||
@@ -94,7 +95,7 @@ export class ContentsController {
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`[stream] content=${content.id}, file=${content.file}, status=${content.status}, project=${content.project?.id}`,
|
||||
`[stream] content=${content.id}, file=${content.file}, status=${content.status}, project=${content.project?.id}, format=${format ?? 'auto'}`,
|
||||
);
|
||||
|
||||
if (!content.file) {
|
||||
@@ -116,6 +117,10 @@ export class ContentsController {
|
||||
|
||||
const dto = new StreamContentDTO(content);
|
||||
|
||||
// When ?format=raw is requested, skip HLS and go straight to presigned URL.
|
||||
// This is used as a fallback when the HLS stream fails (e.g. key decryption issues).
|
||||
const forceRaw = format === 'raw';
|
||||
|
||||
// Check if the HLS manifest actually exists in the public bucket.
|
||||
// In dev (no transcoding pipeline) the raw upload lives in the
|
||||
// private bucket only — fall back to a presigned URL for it.
|
||||
@@ -125,17 +130,21 @@ export class ContentsController {
|
||||
? `${getFileRoute(content.file)}${content.id}/transcoded/file.m3u8`
|
||||
: `${getFileRoute(content.file)}transcoded/file.m3u8`;
|
||||
|
||||
this.logger.log(`[stream] Checking HLS at bucket=${publicBucket}, key=${outputKey}`);
|
||||
if (!forceRaw) {
|
||||
this.logger.log(`[stream] Checking HLS at bucket=${publicBucket}, key=${outputKey}`);
|
||||
|
||||
const hlsExists = await this.uploadService.objectExists(
|
||||
outputKey,
|
||||
publicBucket,
|
||||
);
|
||||
const hlsExists = await this.uploadService.objectExists(
|
||||
outputKey,
|
||||
publicBucket,
|
||||
);
|
||||
|
||||
if (hlsExists) {
|
||||
const publicUrl = getPublicS3Url(outputKey);
|
||||
this.logger.log(`[stream] HLS found, returning publicUrl=${publicUrl}`);
|
||||
return { ...dto, file: publicUrl };
|
||||
if (hlsExists) {
|
||||
const publicUrl = getPublicS3Url(outputKey);
|
||||
this.logger.log(`[stream] HLS found, returning publicUrl=${publicUrl}`);
|
||||
return { ...dto, file: publicUrl };
|
||||
}
|
||||
} else {
|
||||
this.logger.log(`[stream] Raw format requested, skipping HLS check`);
|
||||
}
|
||||
|
||||
// HLS not available — check that the raw file actually exists before
|
||||
|
||||
Reference in New Issue
Block a user