Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: error type enhancement #1478

Merged
merged 12 commits into from
Jan 25, 2024
492 changes: 225 additions & 267 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"video.js": "^7 || ^8"
},
"peerDependencies": {
"video.js": "^7 || ^8"
"video.js": "^8.11.0"
},
"devDependencies": {
"@babel/cli": "^7.21.0",
Expand Down
18 changes: 15 additions & 3 deletions src/dash-playlist-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,8 @@ export default class DashPlaylistLoader extends EventTarget {
message: 'DASH request error at URL: ' + request.uri,
response: request.response,
// MEDIA_ERR_NETWORK
code: 2
code: 2,
metadata: err.metadata
};
if (startingState) {
this.state = startingState;
Expand Down Expand Up @@ -390,6 +391,7 @@ export default class DashPlaylistLoader extends EventTarget {
const uri = resolveManifestRedirect(playlist.sidx.resolvedUri);

const fin = (err, request) => {
// TODO: add error metdata here once we create an error type in video.js
if (this.requestErrored_(err, request, startingState)) {
return;
}
Expand All @@ -400,6 +402,10 @@ export default class DashPlaylistLoader extends EventTarget {
try {
sidx = parseSidx(toUint8(request.response).subarray(8));
} catch (e) {
e.metadata = {
errorType: videojs.Error.DashManifestSidxParsingError
};

// sidx parsing failed.
this.requestErrored_(e, request, startingState);
return;
Expand All @@ -421,17 +427,23 @@ export default class DashPlaylistLoader extends EventTarget {
}

if (!container || container !== 'mp4') {
const sidxContainer = container || 'unknown';

return fin({
status: request.status,
message: `Unsupported ${container || 'unknown'} container type for sidx segment at URL: ${uri}`,
message: `Unsupported ${sidxContainer} container type for sidx segment at URL: ${uri}`,
// response is just bytes in this case
// but we really don't want to return that.
response: '',
playlist,
internal: true,
playlistExclusionDuration: Infinity,
// MEDIA_ERR_NETWORK
code: 2
code: 2,
metadata: {
errorType: videojs.Error.UnsupportedSidxContainer,
sidxContainer
}
}, request);
}

Expand Down
10 changes: 8 additions & 2 deletions src/media-segment-request.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import videojs from 'video.js';
import { createTransferableMessage } from './bin-utils';
import { stringToArrayBuffer } from './util/string-to-array-buffer';
import { transmux } from './segment-transmuxer';
Expand Down Expand Up @@ -159,11 +160,16 @@ const parseInitSegment = (segment, callback) => {
// only know how to parse mp4 init segments at the moment
if (type !== 'mp4') {
const uri = segment.map.resolvedUri || segment.map.uri;
const mediaType = type || 'unknown';

return callback({
internal: true,
message: `Found unsupported ${type || 'unknown'} container for initialization segment at URL: ${uri}`,
code: REQUEST_ERRORS.FAILURE
message: `Found unsupported ${mediaType} container for initialization segment at URL: ${uri}`,
code: REQUEST_ERRORS.FAILURE,
metadata: {
errorType: videojs.UnsupportedMediaInitialization,
dzianis-dashkevich marked this conversation as resolved.
Show resolved Hide resolved
mediaType
}
});
}

Expand Down
10 changes: 8 additions & 2 deletions src/playlist-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,10 @@ export default class PlaylistLoader extends EventTarget {
status: xhr.status,
message: `HLS playlist request error at URL: ${uri}.`,
responseText: xhr.responseText,
code: (xhr.status >= 500) ? 4 : 2
code: (xhr.status >= 500) ? 4 : 2,
metadata: {
errorType: videojs.Error.HlsPlaylistRequestError
}
};

this.trigger('error');
Expand Down Expand Up @@ -854,7 +857,10 @@ export default class PlaylistLoader extends EventTarget {
message: `HLS playlist request error at URL: ${this.src}.`,
responseText: req.responseText,
// MEDIA_ERR_NETWORK
code: 2
code: 2,
metadata: {
errorType: videojs.Error.HlsPlaylistRequestError
}
};
if (this.state === 'HAVE_NOTHING') {
this.started = false;
Expand Down
25 changes: 20 additions & 5 deletions src/segment-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@ export default class SegmentLoader extends videojs.EventTarget {
}

this.pendingSegment_ = null;

return this.error_;
}

Expand Down Expand Up @@ -2268,7 +2269,10 @@ export default class SegmentLoader extends videojs.EventTarget {
`video buffer: ${timeRangesToArray(videoBuffered).join(', ')}, `);
this.error({
message: 'Quota exceeded error with append of a single segment of content',
excludeUntil: Infinity
excludeUntil: Infinity,
metadata: {
errorType: videojs.Error.SegmentExceedsSourceBufferQuota
}
});
this.trigger('error');
return;
Expand Down Expand Up @@ -2323,14 +2327,19 @@ export default class SegmentLoader extends videojs.EventTarget {
}

this.logger_('Received non QUOTA_EXCEEDED_ERR on append', error);
this.error(`${type} append of ${bytes.length}b failed for segment ` +
`#${segmentInfo.mediaIndex} in playlist ${segmentInfo.playlist.id}`);

// If an append errors, we often can't recover.
// (see https://w3c.github.io/media-source/#sourcebuffer-append-error).
//
// Trigger a special error so that it can be handled separately from normal,
// recoverable errors.
this.error({
message: `${type} append of ${bytes.length}b failed for segment ` +
`#${segmentInfo.mediaIndex} in playlist ${segmentInfo.playlist.id}`,
metadata: {
errorType: videojs.Error.SegmentAppendError
}
});
this.trigger('appenderror');
}

Expand Down Expand Up @@ -2811,7 +2820,10 @@ export default class SegmentLoader extends videojs.EventTarget {
if (!trackInfo) {
this.error({
message: 'No starting media returned, likely due to an unsupported media format.',
playlistExclusionDuration: Infinity
playlistExclusionDuration: Infinity,
metadata: {
errorType: videojs.Error.SegmentUnsupportedMediaFormat
}
});
this.trigger('error');
return;
Expand Down Expand Up @@ -2892,7 +2904,10 @@ export default class SegmentLoader extends videojs.EventTarget {
if (illegalMediaSwitchError) {
this.error({
message: illegalMediaSwitchError,
playlistExclusionDuration: Infinity
playlistExclusionDuration: Infinity,
metadata: {
errorType: videojs.Error.SegmentSwitchError
}
});
this.trigger('error');
return true;
Expand Down
5 changes: 4 additions & 1 deletion src/videojs-http-streaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,10 @@ class VhsHandler extends Component {
this.logger_('error while creating EME key session', err);
this.player_.error({
message: 'Failed to initialize media keys for EME',
code: 3
code: 3,
metadata: {
errorType: videojs.Error.EMEKeySessionCreationError
}
});
});
}
Expand Down
12 changes: 10 additions & 2 deletions src/vtt-segment-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,12 @@ export default class VTTSegmentLoader extends SegmentLoader {
this.loadVttJs()
.then(
() => this.segmentRequestFinished_(error, simpleSegment, result),
() => this.stopForError({ message: 'Error loading vtt.js' })
() => this.stopForError({
message: 'Error loading vtt.js',
metadata: {
errorType: videojs.Error.VttLoadError
}
})
);
return;
}
Expand All @@ -325,7 +330,10 @@ export default class VTTSegmentLoader extends SegmentLoader {
this.parseVTTCues_(segmentInfo);
} catch (e) {
this.stopForError({
message: e.message
message: e.message,
metadata: {
errorType: videojs.Error.VttCueParsingError
}
});
return;
}
Expand Down
5 changes: 5 additions & 0 deletions test/dash-playlist-loader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,10 @@ QUnit.test('addSidxSegments_: adds/triggers error on invalid container', functio
code: 2,
internal: true,
message: 'Unsupported unknown container type for sidx segment at URL: sidx.mp4',
metadata: {
errorType: 'unsupported-sidx-container-error',
sidxContainer: 'unknown'
},
playlist,
response: '',
status: 200
Expand Down Expand Up @@ -2022,6 +2026,7 @@ QUnit.test('addSidxSegments_: errors if request for sidx fails', function(assert
{
status: 500,
message: 'DASH request error at URL: sidx.mp4',
metadata: undefined,
response: '',
code: 2
},
Expand Down
5 changes: 4 additions & 1 deletion test/segment-loader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4813,7 +4813,10 @@ QUnit.module('SegmentLoader', function(hooks) {
loader.error_,
{
message: 'Quota exceeded error with append of a single segment of content',
excludeUntil: Infinity
excludeUntil: Infinity,
metadata: {
errorType: 'segment-exceeds-source-buffer-quota-error'
}
},
'loader triggered and saved the error'
);
Expand Down
10 changes: 8 additions & 2 deletions test/videojs-http-streaming.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5149,7 +5149,10 @@ QUnit.test('player error when key session creation rejects promise', function(as
errorObject,
{
code: 3,
message: 'Failed to initialize media keys for EME'
message: 'Failed to initialize media keys for EME',
metadata: {
errorType: 'eme-key-session-creation-error'
}
},
'called player error with correct error'
);
Expand All @@ -5159,7 +5162,10 @@ QUnit.test('player error when key session creation rejects promise', function(as
initializeMediaKeys: (keySystems, callback) => {
// calling back with an error should lead to promise rejection
callback({
message: 'this is the error message'
message: 'this is the error message',
metadata: {
errorType: 'eme-key-session-creation-error'
}
});
}
};
Expand Down
Loading