]>
Commit | Line | Data |
---|---|---|
1 | import { writeJson } from 'fs-extra' | |
2 | import { basename } from 'path' | |
3 | import { mapToJSON } from '@server/helpers/core-utils' | |
4 | import { logger, loggerTagsFactory } from '@server/helpers/logger' | |
5 | import { MStreamingPlaylistVideo } from '@server/types/models' | |
6 | import { buildSha256Segment } from '../hls' | |
7 | import { storeHLSFileFromPath } from '../object-storage' | |
8 | import PQueue from 'p-queue' | |
9 | ||
10 | const lTags = loggerTagsFactory('live') | |
11 | ||
12 | class LiveSegmentShaStore { | |
13 | ||
14 | private readonly segmentsSha256 = new Map<string, string>() | |
15 | ||
16 | private readonly videoUUID: string | |
17 | private readonly sha256Path: string | |
18 | private readonly streamingPlaylist: MStreamingPlaylistVideo | |
19 | private readonly sendToObjectStorage: boolean | |
20 | private readonly writeQueue = new PQueue({ concurrency: 1 }) | |
21 | ||
22 | constructor (options: { | |
23 | videoUUID: string | |
24 | sha256Path: string | |
25 | streamingPlaylist: MStreamingPlaylistVideo | |
26 | sendToObjectStorage: boolean | |
27 | }) { | |
28 | this.videoUUID = options.videoUUID | |
29 | this.sha256Path = options.sha256Path | |
30 | this.streamingPlaylist = options.streamingPlaylist | |
31 | this.sendToObjectStorage = options.sendToObjectStorage | |
32 | } | |
33 | ||
34 | async addSegmentSha (segmentPath: string) { | |
35 | logger.debug('Adding live sha segment %s.', segmentPath, lTags(this.videoUUID)) | |
36 | ||
37 | const shaResult = await buildSha256Segment(segmentPath) | |
38 | ||
39 | const segmentName = basename(segmentPath) | |
40 | this.segmentsSha256.set(segmentName, shaResult) | |
41 | ||
42 | try { | |
43 | await this.writeToDisk() | |
44 | } catch (err) { | |
45 | logger.error('Cannot write sha segments to disk.', { err }) | |
46 | } | |
47 | } | |
48 | ||
49 | async removeSegmentSha (segmentPath: string) { | |
50 | const segmentName = basename(segmentPath) | |
51 | ||
52 | logger.debug('Removing live sha segment %s.', segmentPath, lTags(this.videoUUID)) | |
53 | ||
54 | if (!this.segmentsSha256.has(segmentName)) { | |
55 | logger.warn('Unknown segment in files map for video %s and segment %s.', this.videoUUID, segmentPath, lTags(this.videoUUID)) | |
56 | return | |
57 | } | |
58 | ||
59 | this.segmentsSha256.delete(segmentName) | |
60 | ||
61 | await this.writeToDisk() | |
62 | } | |
63 | ||
64 | private writeToDisk () { | |
65 | return this.writeQueue.add(async () => { | |
66 | await writeJson(this.sha256Path, mapToJSON(this.segmentsSha256)) | |
67 | ||
68 | if (this.sendToObjectStorage) { | |
69 | const url = await storeHLSFileFromPath(this.streamingPlaylist, this.sha256Path) | |
70 | ||
71 | if (this.streamingPlaylist.segmentsSha256Url !== url) { | |
72 | this.streamingPlaylist.segmentsSha256Url = url | |
73 | await this.streamingPlaylist.save() | |
74 | } | |
75 | } | |
76 | }) | |
77 | } | |
78 | } | |
79 | ||
80 | export { | |
81 | LiveSegmentShaStore | |
82 | } |