mirror of
https://github.com/immich-app/immich.git
synced 2026-05-21 23:26:31 -04:00
80 lines
3.3 KiB
TypeScript
80 lines
3.3 KiB
TypeScript
import { Controller, Delete, Get, Header, HttpCode, HttpStatus, Next, Param, Res } from '@nestjs/common';
|
|
import { ApiProduces, ApiTags } from '@nestjs/swagger';
|
|
import { NextFunction, Response } from 'express';
|
|
import { HLS_PLAYLIST_CONTENT_TYPE } from 'src/constants';
|
|
import { Endpoint, HistoryBuilder } from 'src/decorators';
|
|
import { AuthDto } from 'src/dtos/auth.dto';
|
|
import { HlsSegmentParamDto, HlsSessionParamDto, HlsVariantParamDto } from 'src/dtos/streaming.dto';
|
|
import { ApiTag, Permission, RouteKey } from 'src/enum';
|
|
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
|
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
|
import { HlsService } from 'src/services/hls.service';
|
|
import { sendFile } from 'src/utils/file';
|
|
import { UUIDParamDto } from 'src/validation';
|
|
|
|
@ApiTags(ApiTag.Assets)
|
|
@Controller(RouteKey.Asset)
|
|
export class VideoStreamController {
|
|
constructor(
|
|
private logger: LoggingRepository,
|
|
private service: HlsService,
|
|
) {}
|
|
|
|
@Get(':id/video/stream/main.m3u8')
|
|
@Authenticated({ permission: Permission.AssetView, sharedLink: true })
|
|
@Header('Cache-Control', 'no-cache')
|
|
@Header('Content-Type', HLS_PLAYLIST_CONTENT_TYPE)
|
|
@ApiProduces(HLS_PLAYLIST_CONTENT_TYPE)
|
|
@Endpoint({
|
|
summary: 'Get HLS main playlist',
|
|
description: 'Returns an HLS main playlist with all available variants for the asset.',
|
|
history: new HistoryBuilder().added('v3').alpha('v3'),
|
|
})
|
|
getMainPlaylist(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto) {
|
|
return this.service.getMainPlaylist(auth, id);
|
|
}
|
|
|
|
@Get(':id/video/stream/:sessionId/:variantIndex/playlist.m3u8')
|
|
@Authenticated({ permission: Permission.AssetView, sharedLink: true })
|
|
@Header('Cache-Control', 'no-cache')
|
|
@Header('Content-Type', HLS_PLAYLIST_CONTENT_TYPE)
|
|
@ApiProduces(HLS_PLAYLIST_CONTENT_TYPE)
|
|
@Endpoint({
|
|
summary: 'Get HLS media playlist',
|
|
description: 'Returns an HLS media playlist for one variant of the streaming session.',
|
|
history: new HistoryBuilder().added('v3').alpha('v3'),
|
|
})
|
|
getMediaPlaylist(@Auth() auth: AuthDto, @Param() { id, sessionId }: HlsVariantParamDto) {
|
|
return this.service.getMediaPlaylist(auth, id, sessionId);
|
|
}
|
|
|
|
@Get(':id/video/stream/:sessionId/:variantIndex/:filename')
|
|
@FileResponse()
|
|
@Authenticated({ permission: Permission.AssetView, sharedLink: true })
|
|
@Endpoint({
|
|
summary: 'Get HLS segment or init file',
|
|
description: 'Streams an HLS init segment (init.mp4) or media segment (seg_N.m4s).',
|
|
history: new HistoryBuilder().added('v3').alpha('v3'),
|
|
})
|
|
async getSegment(
|
|
@Auth() auth: AuthDto,
|
|
@Param() { id, sessionId, variantIndex, filename }: HlsSegmentParamDto,
|
|
@Res() res: Response,
|
|
@Next() next: NextFunction,
|
|
) {
|
|
await sendFile(res, next, () => this.service.getSegment(auth, id, sessionId, variantIndex, filename), this.logger);
|
|
}
|
|
|
|
@Delete(':id/video/stream/:sessionId')
|
|
@HttpCode(HttpStatus.NO_CONTENT)
|
|
@Authenticated({ permission: Permission.AssetView, sharedLink: true })
|
|
@Endpoint({
|
|
summary: 'End HLS streaming session',
|
|
description: 'Releases server resources for the streaming session.',
|
|
history: new HistoryBuilder().added('v3').alpha('v3'),
|
|
})
|
|
async endSession(@Auth() auth: AuthDto, @Param() { id, sessionId }: HlsSessionParamDto) {
|
|
await this.service.endSession(auth, id, sessionId);
|
|
}
|
|
}
|