Skip to content

Commit

Permalink
fix(#56): update variable handling (#61)
Browse files Browse the repository at this point in the history
* fix: both  and  could be present, causing issues in proxy-manifest build

* chore: reverted ProxyBasenames

* fix: replaces dash with forward slash in url

* chore: add failing unit-test

* wip: variable handling

* fix: handling underscore

* chore: addressed PR comment

---------

Co-authored-by: Benjamin Wallberg <[email protected]>
  • Loading branch information
zapfire88 and bwallberg authored Feb 22, 2024
1 parent d894523 commit 2185e69
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 36 deletions.
22 changes: 22 additions & 0 deletions src/manifests/handlers/dash/segment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import dashSegmentHandler from './segment';

describe('dashSegmentHandler', () => {
it('handles when a representationId contains underscore', async () => {
const result = await dashSegmentHandler({
queryStringParameters: {
url: 'https://stream.with_underscore.com/live-$RepresentationID$-$Time$.dash'
},
path: '/segment_82008145102133_123_audio_track_0_0_nor=128000_128000',
requestContext: {
elb: { targetGroupArn: '' }
},
isBase64Encoded: false,
httpMethod: 'GET',
body: '',
headers: {}
});
expect(result.headers.Location).toBe(
'https://stream.with_underscore.com/live-audio_track_0_0_nor=128000_128000-82008145102133.dash'
);
});
});
27 changes: 17 additions & 10 deletions src/manifests/handlers/dash/segment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,33 @@ export default async function dashSegmentHandler(
const urlSearchParams = new URLSearchParams(event.queryStringParameters);
const pathStem = path.basename(event.path).replace('.mp4', '');
// Get the number part after "segment_"
const [, reqSegmentIndexStr, representationIdStr, bitrateStr, timeStr] =
const [, reqSegmentIndexOrTimeStr, bitrateStr, ...representationIdStrList] =
pathStem.split('_');
const representationIdStr = representationIdStrList.join('_');
// Build correct Source Segment url
// segment templates may contain a width parameter "$Number%0[width]d$", and then we need to zero-pad them to that length
let segmentUrl = url
.replace(/\$Number%0(\d+)d\$/, (_, width) =>
reqSegmentIndexStr.padStart(Number(width), '0')
)
.replace('$Number$', reqSegmentIndexStr);
const reqSegmentIndexInt = parseInt(reqSegmentIndexStr);

let segmentUrl = url;

if (segmentUrl.includes('$Time$')) {
segmentUrl = segmentUrl.replace('$Time$', reqSegmentIndexOrTimeStr);
} else {
segmentUrl = segmentUrl
.replace(/\$Number%0(\d+)d\$/, (_, width) =>
reqSegmentIndexOrTimeStr.padStart(Number(width), '0')
)
.replace('$Number$', reqSegmentIndexOrTimeStr);
}
const reqSegmentIndexInt = parseInt(reqSegmentIndexOrTimeStr);

// Replace RepresentationID in url if present
if (representationIdStr) {
segmentUrl = segmentUrl.replace(
'$RepresentationID$',
representationIdStr
);
}
if (timeStr) {
segmentUrl = segmentUrl.replace('$Time$', timeStr);
}

if (bitrateStr) {
urlSearchParams.set('bitrate', bitrateStr);
}
Expand Down
19 changes: 12 additions & 7 deletions src/manifests/utils/dashManifestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default function (): DASHManifestTools {

// Media attr
const mediaUrl = segmentTemplate.$.media;

const hasTime = mediaUrl.toString().includes('$Time$');
// Convert relative segment offsets to absolute ones
// Also clones params to avoid mutating input argument
const [urlQuery, changed] = convertRelativeToAbsoluteSegmentOffsets(
Expand All @@ -99,12 +99,14 @@ export default function (): DASHManifestTools {
);

if (changed) staticQueryUrl = new URLSearchParams(urlQuery);

segmentTemplate.$.media = proxyPathBuilder(
const proxy = proxyPathBuilder(
mediaUrl.match(/^http/) ? mediaUrl : baseUrl + mediaUrl,
urlQuery,
'proxy-segment/segment_$Number$_$RepresentationID$_$Bandwidth$_$Time$'
hasTime
? 'proxy-segment/segment_$Time$_$Bandwidth$_$RepresentationID$'
: 'proxy-segment/segment_$Number$_$Bandwidth$_$RepresentationID$'
);
segmentTemplate.$.media = proxy;
// Initialization attr.
const initUrl = segmentTemplate.$.initialization;
if (!initUrl.match(/^http/)) {
Expand All @@ -128,7 +130,7 @@ export default function (): DASHManifestTools {
representation.SegmentTemplate.map((segmentTemplate) => {
// Media attr.
const mediaUrl = segmentTemplate.$.media;

const hasTime = mediaUrl.toString().includes('$Time$');
// Convert relative segment offsets to absolute ones
// Also clones params to avoid mutating input argument
const [urlQuery, changed] =
Expand All @@ -145,11 +147,14 @@ export default function (): DASHManifestTools {
urlQuery.set('bitrate', representation.$.bandwidth);
}

segmentTemplate.$.media = proxyPathBuilder(
const proxy = proxyPathBuilder(
mediaUrl,
urlQuery,
'proxy-segment/segment_$Number$.mp4'
hasTime
? 'proxy-segment/segment_$Time$.mp4'
: 'proxy-segment/segment_$Number$.mp4'
);
segmentTemplate.$.media = proxy;
// Initialization attr.
const masterDashUrl = originalUrlQuery.get('url');
const initUrl = segmentTemplate.$.initialization;
Expand Down
28 changes: 15 additions & 13 deletions src/manifests/utils/hlsManifestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ export default function (): HLSManifestTools {
if (stateKey) {
urlQuery.set('state', stateKey);
}
streamItem.set(
'uri',
proxyPathBuilder(currentUri, urlQuery, 'proxy-media.m3u8')
const proxy = proxyPathBuilder(
currentUri,
urlQuery,
'proxy-media.m3u8'
);
streamItem.set('uri', proxy);
return streamItem;
});

Expand All @@ -119,10 +121,12 @@ export default function (): HLSManifestTools {
if (stateKey) {
urlQuery.set('state', stateKey);
}
mediaItem.set(
'uri',
proxyPathBuilder(currentUri, originalUrlQuery, 'proxy-media.m3u8')
const proxy = proxyPathBuilder(
currentUri,
urlQuery,
'proxy-media.m3u8'
);
mediaItem.set('uri', proxy);
return mediaItem;
});

Expand Down Expand Up @@ -159,14 +163,12 @@ export default function (): HLSManifestTools {
}

const params = segmentUrlParamString(sourceSegURL, corruption);
item.set(
'uri',
proxyPathBuilder(
item.get('uri'),
new URLSearchParams(params),
'../../segments/proxy-segment'
)
const proxy = proxyPathBuilder(
item.get('uri'),
new URLSearchParams(params),
'../../segments/proxy-segment'
);
item.set('uri', proxy);
}
return m3u.toString();
}
Expand Down
7 changes: 5 additions & 2 deletions src/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,11 @@ type ProxyBasenames =
| 'proxy-media.m3u8'
| '../../segments/proxy-segment'
| 'proxy-segment/segment_$Number$.mp4'
| 'proxy-segment/segment_$Number$_$RepresentationID$_$Bandwidth$'
| 'proxy-segment/segment_$Number$_$RepresentationID$_$Bandwidth$_$Time$';
| 'proxy-segment/segment_$Time$.mp4'
| 'proxy-segment/segment_$Number$_$RepresentationID$'
| 'proxy-segment/segment_$Time$_$RepresentationID$'
| 'proxy-segment/segment_$Number$_$Bandwidth$_$RepresentationID$'
| 'proxy-segment/segment_$Time$_$Bandwidth$_$RepresentationID$';

/**
* Adjust paths based on directory navigation
Expand Down
4 changes: 2 additions & 2 deletions src/testvectors/dash/dash1_compressed/proxy-manifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<SegmentTemplate
timescale="48000"
initialization="https://mock.mock.com/stream/relative_base/audiotrack/init/$RepresentationID$.m4s"
media="proxy-segment/segment_$Number$_$RepresentationID$_$Bandwidth$_$Time$?url=https%3A%2F%2Fmock.mock.com%2Fstream%2Frelative_base%2Faudiotrack%2F%24RepresentationID%24%2F%24Time%24.m4s&amp;statusCode=%5B%7Bi%3A0%2Ccode%3A404%7D%2C%7Bi%3A2%2Ccode%3A401%7D%5D&amp;timeout=%5B%7Bi%3A3%7D%5D&amp;delay=%5B%7Bi%3A2%2Cms%3A2000%7D%5D">
media="proxy-segment/segment_$Time$_$Bandwidth$_$RepresentationID$?url=https%3A%2F%2Fmock.mock.com%2Fstream%2Frelative_base%2Faudiotrack%2F%24RepresentationID%24%2F%24Time%24.m4s&amp;statusCode=%5B%7Bi%3A0%2Ccode%3A404%7D%2C%7Bi%3A2%2Ccode%3A401%7D%5D&amp;timeout=%5B%7Bi%3A3%7D%5D&amp;delay=%5B%7Bi%3A2%2Cms%3A2000%7D%5D">
<SegmentTimeline>
<S t="80746389121167" d="184320" r="78" />
</SegmentTimeline>
Expand Down Expand Up @@ -62,7 +62,7 @@
<SegmentTemplate
timescale="600"
initialization="https://mock.mock.com/stream/relative_base/videotrack/init/$RepresentationID$.m4s"
media="proxy-segment/segment_$Number$_$RepresentationID$_$Bandwidth$_$Time$?url=https%3A%2F%2Fmock.mock.com%2Fstream%2Frelative_base%2Fvideotrack%2F%24RepresentationID%24%2F%24Time%24.m4s&amp;statusCode=%5B%7Bi%3A0%2Ccode%3A404%7D%2C%7Bi%3A2%2Ccode%3A401%7D%5D&amp;timeout=%5B%7Bi%3A3%7D%5D&amp;delay=%5B%7Bi%3A2%2Cms%3A2000%7D%5D">
media="proxy-segment/segment_$Time$_$Bandwidth$_$RepresentationID$?url=https%3A%2F%2Fmock.mock.com%2Fstream%2Frelative_base%2Fvideotrack%2F%24RepresentationID%24%2F%24Time%24.m4s&amp;statusCode=%5B%7Bi%3A0%2Ccode%3A404%7D%2C%7Bi%3A2%2Ccode%3A401%7D%5D&amp;timeout=%5B%7Bi%3A3%7D%5D&amp;delay=%5B%7Bi%3A2%2Cms%3A2000%7D%5D">
<SegmentTimeline>
<S t="1009329864060" d="2304" r="78" />
</SegmentTimeline>
Expand Down
4 changes: 2 additions & 2 deletions src/testvectors/dash/dash_period_baseurl/proxy-manifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011" minBufferTime="PT1.500S" type="static" mediaPresentationDuration="PT0H0M10.000S" maxSegmentDuration="PT0H0M1.000S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd">
<Period id="0" start="PT0H0M0.000S">
<AdaptationSet mimeType="video/mp4" codecs="avc1.4D401E" frameRate="30000/1001" lang="und">
<SegmentTemplate timescale="1000" media="proxy-segment/segment_$Number$_$RepresentationID$_$Bandwidth$_$Time$?url=http%3A%2F%2Fvm2.dashif.org%2Flivesim-dev%2Fperiods_60%2Fvideo_%24Number%24.mp4" initialization="http://vm2.dashif.org/livesim-dev/periods_60/video_init.mp4" startNumber="1" presentationTimeOffset="0">
<SegmentTemplate timescale="1000" media="proxy-segment/segment_$Number$_$Bandwidth$_$RepresentationID$?url=http%3A%2F%2Fvm2.dashif.org%2Flivesim-dev%2Fperiods_60%2Fvideo_%24Number%24.mp4" initialization="http://vm2.dashif.org/livesim-dev/periods_60/video_init.mp4" startNumber="1" presentationTimeOffset="0">
<SegmentTimeline>
<S t="0" d="10000"/>
<S t="10000" d="10000"/>
Expand All @@ -17,7 +17,7 @@
</SegmentTemplate>
</AdaptationSet>
<AdaptationSet mimeType="audio/mp4" lang="und">
<SegmentTemplate timescale="1000" media="proxy-segment/segment_$Number$_$RepresentationID$_$Bandwidth$_$Time$?url=http%3A%2F%2Fvm2.dashif.org%2Flivesim-dev%2Fperiods_60%2Faudio_%24Number%24.mp4" initialization="http://vm2.dashif.org/livesim-dev/periods_60/audio_init.mp4" startNumber="1" presentationTimeOffset="0">
<SegmentTemplate timescale="1000" media="proxy-segment/segment_$Number$_$Bandwidth$_$RepresentationID$?url=http%3A%2F%2Fvm2.dashif.org%2Flivesim-dev%2Fperiods_60%2Faudio_%24Number%24.mp4" initialization="http://vm2.dashif.org/livesim-dev/periods_60/audio_init.mp4" startNumber="1" presentationTimeOffset="0">
<SegmentTimeline>
<S t="0" d="10000"/>
<S t="10000" d="10000"/>
Expand Down

0 comments on commit 2185e69

Please sign in to comment.