Skip to content

Commit b77dbe8

Browse files
authored
Merge pull request #38 from dfpc-coe/password
Retain Credentials
2 parents 27af9f0 + 59d406e commit b77dbe8

File tree

7 files changed

+553
-496
lines changed

7 files changed

+553
-496
lines changed

lib/manifest.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { URL } from 'node:url';
2+
import path from 'node:path';
3+
import { randomUUID } from 'node:crypto';
4+
import { generateSignedUrl } from './signing.js';
5+
import type { Config } from './config.js';
6+
import NodeCache from 'node-cache';
7+
import Err from '@openaddresses/batch-error';
8+
9+
export class Manifest {
10+
static rewrite(
11+
content: string,
12+
baseUrl: string,
13+
stream: string,
14+
config: Config,
15+
cache: NodeCache
16+
): string {
17+
if (!content.startsWith('#EXTM3U')) {
18+
console.error('Invalid M3U8 Manifest:', content);
19+
throw new Err(400, null, 'Invalid M3U8 Manifest');
20+
}
21+
22+
const lines = content.split('\n');
23+
24+
const transformed = lines.map((line) => {
25+
const trimmed = line.trim();
26+
27+
if (!trimmed) return line;
28+
29+
// Handle EXT-X-MAP
30+
if (trimmed.startsWith('#EXT-X-MAP:URI')) {
31+
const absoluteUrl = new URL(
32+
trimmed
33+
.replace(/#EXT-X-MAP:URI=/, '')
34+
.replace(/^"/, '')
35+
.replace(/"$/, ''),
36+
baseUrl).href;
37+
38+
const resourceHash = randomUUID();
39+
cache.set(`${stream}-${resourceHash}`, absoluteUrl);
40+
const signedUrl = generateSignedUrl(config.SigningSecret, stream, resourceHash, 'mp4');
41+
return `#EXT-X-MAP:URI="${signedUrl}"`;
42+
}
43+
44+
// Handle EXT-X-MEDIA
45+
if (trimmed.startsWith('#EXT-X-MEDIA:TYPE')) {
46+
if (trimmed.includes('URI=')) {
47+
const parts = trimmed.split('URI=');
48+
const uriPart = parts[1];
49+
const uri = uriPart.replace(/^"/, '').replace(/"$/, '');
50+
const absoluteUrl = new URL(uri, baseUrl).href;
51+
52+
const resourceHash = randomUUID();
53+
cache.set(`${stream}-${resourceHash}`, absoluteUrl);
54+
const signedUrl = generateSignedUrl(config.SigningSecret, stream, resourceHash, 'm3u8');
55+
56+
return `${parts[0]}URI="${signedUrl}"`;
57+
}
58+
return line;
59+
}
60+
61+
// Pass through other tags
62+
if (trimmed.startsWith('#')) {
63+
return line;
64+
}
65+
66+
// Handle URLs
67+
const absoluteUrl = new URL(trimmed, baseUrl).href;
68+
const resourceHash = randomUUID();
69+
cache.set(`${stream}-${resourceHash}`, absoluteUrl);
70+
71+
const ext = path.parse(absoluteUrl.split('?')[0]).ext;
72+
73+
if (ext && ext.length > 1) {
74+
return generateSignedUrl(config.SigningSecret, stream, resourceHash, ext.slice(1));
75+
} else {
76+
throw new Err(400, null, `Unsupported media segment type: ${ext}`);
77+
}
78+
});
79+
80+
return transformed.join('\n');
81+
}
82+
}

lib/signing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export function generateSignedUrl(
44
secret: string,
55
path: string,
66
hash: string,
7-
type: 'ts' | 'm4s' | 'm3u8' | 'mp4'
7+
type: string
88
): string {
99
const exp = Math.floor(Date.now() / 1000) + 600;
1010
const signature = crypto

mediamtx.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ authInternalUsers: []
1616
api: yes
1717
apiAddress: :4000
1818
apiEncryption: no
19-
apiAllowOrigin: '*'
19+
apiAllowOrigins: ['*']
2020
apiTrustedProxies: []
2121

2222
playback: yes
@@ -39,7 +39,7 @@ hlsEncryption: no
3939
webrtc: no
4040
webrtcAddress: :8889
4141
webrtcEncryption: no
42-
webrtcAllowOrigin: '*'
42+
webrtcAllowOrigins: ['*']
4343

4444
srt: yes
4545
srtAddress: :8890

0 commit comments

Comments
 (0)