shaka-player 4.2.12 → 4.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +11 -0
  2. package/.github/workflows/build-and-test.yaml +22 -14
  3. package/.github/workflows/compute-incremental-coverage.py +3 -0
  4. package/.github/workflows/selenium-lab-tests.yaml +48 -12
  5. package/.github/workflows/update-issues.yaml +1 -0
  6. package/CHANGELOG.md +28 -0
  7. package/demo/common/assets.js +12 -12
  8. package/demo/main.js +5 -0
  9. package/dist/demo.compiled.debug.js +13 -13
  10. package/dist/demo.compiled.debug.map +2 -2
  11. package/dist/demo.compiled.js +13 -13
  12. package/dist/demo.compiled.map +2 -2
  13. package/dist/deps.js +1 -1
  14. package/dist/locales.js +31 -31
  15. package/dist/receiver.compiled.debug.js +8 -8
  16. package/dist/receiver.compiled.debug.map +1 -1
  17. package/dist/receiver.compiled.js +8 -8
  18. package/dist/receiver.compiled.map +1 -1
  19. package/dist/shaka-player.compiled.d.ts +2 -2
  20. package/dist/shaka-player.compiled.debug.d.ts +2 -2
  21. package/dist/shaka-player.compiled.debug.js +51 -49
  22. package/dist/shaka-player.compiled.debug.map +3 -3
  23. package/dist/shaka-player.compiled.js +403 -404
  24. package/dist/shaka-player.compiled.map +3 -3
  25. package/dist/shaka-player.ui.d.ts +2 -2
  26. package/dist/shaka-player.ui.debug.d.ts +2 -2
  27. package/dist/shaka-player.ui.debug.js +60 -59
  28. package/dist/shaka-player.ui.debug.map +3 -3
  29. package/dist/shaka-player.ui.js +411 -411
  30. package/dist/shaka-player.ui.map +2 -2
  31. package/docs/tutorials/selenium-grid-config.md +60 -8
  32. package/externs/shaka/manifest.js +5 -1
  33. package/externs/shaka/offline.js +5 -1
  34. package/karma.conf.js +52 -7
  35. package/lib/abr/simple_abr_manager.js +5 -5
  36. package/lib/ads/client_side_ad_manager.js +14 -2
  37. package/lib/dash/dash_parser.js +1 -0
  38. package/lib/hls/hls_parser.js +1 -0
  39. package/lib/media/media_source_engine.js +6 -5
  40. package/lib/media/streaming_engine.js +2 -2
  41. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  42. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  43. package/lib/offline/manifest_converter.js +1 -0
  44. package/lib/offline/storage.js +1 -0
  45. package/lib/player.js +4 -5
  46. package/lib/polyfill/orientation.js +34 -7
  47. package/lib/text/vtt_text_parser.js +1 -0
  48. package/lib/util/manifest_parser_utils.js +4 -2
  49. package/lib/util/periods.js +2 -0
  50. package/lib/util/platform.js +22 -0
  51. package/lib/util/stream_utils.js +69 -26
  52. package/package.json +3 -3
  53. package/test/cast/cast_utils_unit.js +4 -1
  54. package/test/hls/hls_parser_unit.js +72 -0
  55. package/test/media/adaptation_set_unit.js +1 -0
  56. package/test/media/drm_engine_integration.js +2 -2
  57. package/test/media/media_source_engine_unit.js +1 -1
  58. package/test/media/segment_index_unit.js +3 -3
  59. package/test/media/streaming_engine_integration.js +14 -11
  60. package/test/offline/manifest_convert_unit.js +5 -0
  61. package/test/offline/offline_integration.js +6 -3
  62. package/test/player_external.js +19 -16
  63. package/test/player_integration.js +39 -49
  64. package/test/player_src_equals_integration.js +9 -5
  65. package/test/test/util/fake_demo_main.js +7 -3
  66. package/test/test/util/layout_tests.js +2 -2
  67. package/test/test/util/manifest_generator.js +2 -0
  68. package/test/test/util/offline_utils.js +1 -0
  69. package/test/test/util/streaming_engine_util.js +3 -0
  70. package/test/test/util/ui_utils.js +14 -3
  71. package/test/test/util/util.js +6 -27
  72. package/test/test/util/waiter.js +73 -3
  73. package/test/ui/ad_ui_unit.js +9 -9
  74. package/test/util/stream_utils_unit.js +46 -0
  75. package/ui/externs/ui.js +2 -2
  76. package/ui/range_element.js +5 -0
  77. package/ui/seek_bar.js +7 -1
@@ -436,47 +436,61 @@ shaka.util.StreamUtils = class {
436
436
  manifest.variants = manifest.variants.filter((variant) => {
437
437
  // See: https://github.com/shaka-project/shaka-player/issues/3860
438
438
  const video = variant.video;
439
+
439
440
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
441
+ const ManifestParserUtils = shaka.util.ManifestParserUtils;
442
+ const MimeUtils = shaka.util.MimeUtils;
443
+ const StreamUtils = shaka.util.StreamUtils;
444
+
440
445
  if (video) {
441
- let videoCodecs =
442
- shaka.util.StreamUtils.getCorrectVideoCodecs_(video.codecs);
446
+ let videoCodecs = StreamUtils.getCorrectVideoCodecs_(video.codecs);
447
+
443
448
  // For multiplexed streams. Here we must check the audio of the
444
449
  // stream to see if it is compatible.
445
450
  if (video.codecs.includes(',')) {
446
451
  const allCodecs = video.codecs.split(',');
447
- videoCodecs = shaka.util.ManifestParserUtils.guessCodecs(
452
+
453
+ videoCodecs = ManifestParserUtils.guessCodecs(
448
454
  ContentType.VIDEO, allCodecs);
449
- videoCodecs =
450
- shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs);
451
- let audioCodecs = shaka.util.ManifestParserUtils.guessCodecs(
455
+ videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
456
+
457
+ let audioCodecs = ManifestParserUtils.guessCodecs(
452
458
  ContentType.AUDIO, allCodecs);
453
- audioCodecs =
454
- shaka.util.StreamUtils.getCorrectAudioCodecs_(audioCodecs);
455
- const audioFullType = shaka.util.MimeUtils.getFullOrConvertedType(
459
+ audioCodecs = StreamUtils.getCorrectAudioCodecs_(audioCodecs);
460
+
461
+ const audioFullType = MimeUtils.getFullOrConvertedType(
456
462
  video.mimeType, audioCodecs, ContentType.AUDIO);
463
+
457
464
  if (!MediaSource.isTypeSupported(audioFullType)) {
458
465
  return false;
459
466
  }
467
+
460
468
  // Update the codec string with the (possibly) converted codecs.
461
469
  videoCodecs = [videoCodecs, audioCodecs].join(',');
462
470
  }
463
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
471
+
472
+ const fullType = MimeUtils.getFullOrConvertedType(
464
473
  video.mimeType, videoCodecs, ContentType.VIDEO);
474
+
465
475
  if (!MediaSource.isTypeSupported(fullType)) {
466
476
  return false;
467
477
  }
478
+
468
479
  // Update the codec string with the (possibly) converted codecs.
469
480
  video.codecs = videoCodecs;
470
481
  }
482
+
471
483
  const audio = variant.audio;
484
+
472
485
  if (audio) {
473
- const codecs =
474
- shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
475
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
486
+ const codecs = StreamUtils.getCorrectAudioCodecs_(audio.codecs);
487
+ const fullType = MimeUtils.getFullOrConvertedType(
476
488
  audio.mimeType, codecs, ContentType.AUDIO);
489
+
477
490
  if (!MediaSource.isTypeSupported(fullType)) {
478
491
  return false;
479
492
  }
493
+
480
494
  // Update the codec string with the (possibly) converted codecs.
481
495
  audio.codecs = codecs;
482
496
  }
@@ -488,7 +502,7 @@ shaka.util.StreamUtils = class {
488
502
  (video.codecs.includes('avc1.') ||
489
503
  video.codecs.includes('avc3.'))) {
490
504
  shaka.log.debug('Dropping variant - not compatible with platform',
491
- shaka.util.StreamUtils.getVariantSummaryString_(variant));
505
+ StreamUtils.getVariantSummaryString_(variant));
492
506
  return false;
493
507
  }
494
508
 
@@ -498,7 +512,7 @@ shaka.util.StreamUtils = class {
498
512
  // Filter out all unsupported variants.
499
513
  if (!supported) {
500
514
  shaka.log.debug('Dropping variant - not compatible with platform',
501
- shaka.util.StreamUtils.getVariantSummaryString_(variant));
515
+ StreamUtils.getVariantSummaryString_(variant));
502
516
  }
503
517
  return supported;
504
518
  });
@@ -562,7 +576,11 @@ shaka.util.StreamUtils = class {
562
576
  static getDecodingConfigs_(variant, usePersistentLicenses, srcEquals) {
563
577
  const audio = variant.audio;
564
578
  const video = variant.video;
579
+
565
580
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
581
+ const ManifestParserUtils = shaka.util.ManifestParserUtils;
582
+ const MimeUtils = shaka.util.MimeUtils;
583
+ const StreamUtils = shaka.util.StreamUtils;
566
584
 
567
585
  /** @type {!MediaDecodingConfiguration} */
568
586
  const mediaDecodingConfig = {
@@ -571,19 +589,23 @@ shaka.util.StreamUtils = class {
571
589
 
572
590
  if (video) {
573
591
  let videoCodecs = video.codecs;
592
+
574
593
  // For multiplexed streams with audio+video codecs, the config should have
575
594
  // AudioConfiguration and VideoConfiguration.
576
595
  if (video.codecs.includes(',')) {
577
596
  const allCodecs = video.codecs.split(',');
578
- videoCodecs = shaka.util.ManifestParserUtils.guessCodecs(
597
+
598
+ videoCodecs = ManifestParserUtils.guessCodecs(
579
599
  ContentType.VIDEO, allCodecs);
580
- videoCodecs =
581
- shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs);
582
- const audioCodecs = shaka.util.ManifestParserUtils.guessCodecs(
600
+ videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
601
+
602
+ let audioCodecs = ManifestParserUtils.guessCodecs(
583
603
  ContentType.AUDIO, allCodecs);
604
+ audioCodecs = StreamUtils.getCorrectAudioCodecs_(audioCodecs);
584
605
 
585
- const audioFullType = shaka.util.MimeUtils.getFullOrConvertedType(
606
+ const audioFullType = MimeUtils.getFullOrConvertedType(
586
607
  video.mimeType, audioCodecs, ContentType.AUDIO);
608
+
587
609
  mediaDecodingConfig.audio = {
588
610
  contentType: audioFullType,
589
611
  channels: 2,
@@ -592,9 +614,11 @@ shaka.util.StreamUtils = class {
592
614
  spatialRendering: false,
593
615
  };
594
616
  }
595
- videoCodecs = shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs);
596
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
617
+
618
+ videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
619
+ const fullType = MimeUtils.getFullOrConvertedType(
597
620
  video.mimeType, videoCodecs, ContentType.VIDEO);
621
+
598
622
  // VideoConfiguration
599
623
  mediaDecodingConfig.video = {
600
624
  contentType: fullType,
@@ -627,9 +651,8 @@ shaka.util.StreamUtils = class {
627
651
  }
628
652
  }
629
653
  if (audio) {
630
- const codecs =
631
- shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
632
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
654
+ const codecs = StreamUtils.getCorrectAudioCodecs_(audio.codecs);
655
+ const fullType = MimeUtils.getFullOrConvertedType(
633
656
  audio.mimeType, codecs, ContentType.AUDIO);
634
657
 
635
658
  // AudioConfiguration
@@ -760,6 +783,20 @@ shaka.util.StreamUtils = class {
760
783
  * @private
761
784
  */
762
785
  static getCorrectAudioCodecs_(codecs) {
786
+ // According to RFC 6381 section 3.3, 'fLaC' is actually the correct
787
+ // codec string. We still need to map it to 'flac', as some browsers
788
+ // currently don't support 'fLaC', while 'flac' is supported by most
789
+ // major browsers.
790
+ // See https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
791
+ if (codecs === 'fLaC') {
792
+ return 'flac';
793
+ }
794
+
795
+ // The same is true for 'Opus'.
796
+ if (codecs === 'Opus') {
797
+ return 'opus';
798
+ }
799
+
763
800
  // Some Tizen devices seem to misreport AC-3 support, but correctly
764
801
  // report EC-3 support. So query EC-3 as a fallback for AC-3.
765
802
  // See https://github.com/shaka-project/shaka-player/issues/2989 for
@@ -1238,6 +1275,9 @@ shaka.util.StreamUtils = class {
1238
1275
  if (textTrack.kind == 'captions') {
1239
1276
  track.mimeType = CLOSED_CAPTION_MIMETYPE;
1240
1277
  }
1278
+ if (textTrack.kind == 'subtitles') {
1279
+ track.mimeType = 'text/vtt';
1280
+ }
1241
1281
  if (textTrack.kind) {
1242
1282
  track.roles = [textTrack.kind];
1243
1283
  }
@@ -1285,13 +1325,15 @@ shaka.util.StreamUtils = class {
1285
1325
  * @private
1286
1326
  */
1287
1327
  static html5TrackToGenericShakaTrack_(html5Track) {
1328
+ const language = html5Track.language;
1329
+
1288
1330
  /** @type {shaka.extern.Track} */
1289
1331
  const track = {
1290
1332
  id: shaka.util.StreamUtils.html5TrackId(html5Track),
1291
1333
  active: false,
1292
1334
  type: '',
1293
1335
  bandwidth: 0,
1294
- language: shaka.util.LanguageUtils.normalize(html5Track.language),
1336
+ language: shaka.util.LanguageUtils.normalize(language || 'und'),
1295
1337
  label: html5Track.label,
1296
1338
  kind: html5Track.kind,
1297
1339
  width: null,
@@ -1321,6 +1363,7 @@ shaka.util.StreamUtils = class {
1321
1363
  originalAudioId: null,
1322
1364
  originalTextId: null,
1323
1365
  originalImageId: null,
1366
+ originalLanguage: language,
1324
1367
  };
1325
1368
 
1326
1369
  return track;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "4.2.12",
4
+ "version": "4.2.14",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -14,6 +14,7 @@
14
14
  "@babel/core": "^7.17.5",
15
15
  "@babel/polyfill": "^7.12.1",
16
16
  "@babel/preset-env": "^7.16.11",
17
+ "@joeyparrish/karma-babel-preprocessor": "^8.2.0",
17
18
  "@teppeis/clutz": "^1.0.29-4c95e12.v20190929",
18
19
  "awesomplete": "^1.1.5",
19
20
  "babel-plugin-istanbul": "^6.1.1",
@@ -38,11 +39,10 @@
38
39
  "js-yaml": "^4.1.0",
39
40
  "jsdoc": "github:joeyparrish/jsdoc#2ca85bb6",
40
41
  "karma": "^6.3.16",
41
- "karma-babel-preprocessor": "^8.0.2",
42
42
  "karma-coverage": "^2.2.0",
43
43
  "karma-jasmine": "^4.0.1",
44
44
  "karma-jasmine-ajax": "^0.1.13",
45
- "karma-local-wd-launcher": "^1.6.2",
45
+ "karma-local-wd-launcher": "^1.6.4",
46
46
  "karma-opera-launcher": "^1.0.0",
47
47
  "karma-sourcemap-loader": "^0.3.8",
48
48
  "karma-spec-reporter": "^0.0.34",
@@ -171,7 +171,10 @@ describe('CastUtils', () => {
171
171
  }
172
172
  });
173
173
 
174
- describe('TimeRanges', () => {
174
+ // Disable because these tests are flakey on ChromeLinux, and this whole
175
+ // module will be removed in
176
+ // https://github.com/shaka-project/shaka-player/issues/4214
177
+ xdescribe('TimeRanges', () => {
175
178
  /** @type {!HTMLVideoElement} */
176
179
  let video;
177
180
  /** @type {!shaka.util.EventManager} */
@@ -573,6 +573,78 @@ describe('HlsParser', () => {
573
573
  await testHlsParser(master, media, manifest);
574
574
  });
575
575
 
576
+ it('accepts fLaC codec as audio/mp4', async () => {
577
+ const master = [
578
+ '#EXTM3U\n',
579
+ '#EXT-X-STREAM-INF:BANDWIDTH=1000000,CODECS="fLaC"\n',
580
+ 'audio\n',
581
+ '#EXT-X-STREAM-INF:BANDWIDTH=1000000,CODECS="flac"\n',
582
+ 'audio2\n',
583
+ ].join('');
584
+
585
+ const media = [
586
+ '#EXTM3U\n',
587
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
588
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
589
+ '#EXTINF:5,\n',
590
+ '#EXT-X-BYTERANGE:121090@616\n',
591
+ 'main.mp4',
592
+ ].join('');
593
+
594
+ const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
595
+ manifest.anyTimeline();
596
+ manifest.addPartialVariant((variant) => {
597
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
598
+ stream.mime('audio/mp4', 'fLaC');
599
+ });
600
+ });
601
+ manifest.addPartialVariant((variant) => {
602
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
603
+ stream.mime('audio/mp4', 'flac');
604
+ });
605
+ });
606
+ manifest.sequenceMode = true;
607
+ });
608
+
609
+ await testHlsParser(master, media, manifest);
610
+ });
611
+
612
+ it('accepts Opus codec as audio/mp4', async () => {
613
+ const master = [
614
+ '#EXTM3U\n',
615
+ '#EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS="Opus"\n',
616
+ 'audio\n',
617
+ '#EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS="opus"\n',
618
+ 'audio2\n',
619
+ ].join('');
620
+
621
+ const media = [
622
+ '#EXTM3U\n',
623
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
624
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
625
+ '#EXTINF:5,\n',
626
+ '#EXT-X-BYTERANGE:121090@616\n',
627
+ 'main.mp4',
628
+ ].join('');
629
+
630
+ const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
631
+ manifest.anyTimeline();
632
+ manifest.addPartialVariant((variant) => {
633
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
634
+ stream.mime('audio/mp4', 'Opus');
635
+ });
636
+ });
637
+ manifest.addPartialVariant((variant) => {
638
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
639
+ stream.mime('audio/mp4', 'opus');
640
+ });
641
+ });
642
+ manifest.sequenceMode = true;
643
+ });
644
+
645
+ await testHlsParser(master, media, manifest);
646
+ });
647
+
576
648
  it('parses audio+video variant with closed captions', async () => {
577
649
  const master = [
578
650
  '#EXTM3U\n',
@@ -218,6 +218,7 @@ describe('AdaptationSet', () => {
218
218
  forced: false,
219
219
  trickModeVideo: null,
220
220
  type: '',
221
+ external: false,
221
222
  };
222
223
  }
223
224
  });
@@ -242,7 +242,7 @@ describe('DrmEngine', () => {
242
242
  /* hasClosedCaptions= */ false);
243
243
 
244
244
  expect(video.buffered.end(0)).toBeGreaterThan(0);
245
- video.play();
245
+ await video.play();
246
246
 
247
247
  const waiter = new shaka.test.Waiter(eventManager).timeoutAfter(15);
248
248
  waiter.setMediaSourceEngine(mediaSourceEngine);
@@ -325,7 +325,7 @@ describe('DrmEngine', () => {
325
325
  /* hasClosedCaptions= */ false);
326
326
 
327
327
  expect(video.buffered.end(0)).toBeGreaterThan(0);
328
- video.play();
328
+ await video.play();
329
329
 
330
330
  const waiter = new shaka.test.Waiter(eventManager).timeoutAfter(15);
331
331
  waiter.setMediaSourceEngine(mediaSourceEngine);
@@ -1258,7 +1258,7 @@ describe('MediaSourceEngine', () => {
1258
1258
  });
1259
1259
 
1260
1260
  it('destroys text engines', async () => {
1261
- mediaSourceEngine.reinitText('text/vtt', false);
1261
+ mediaSourceEngine.reinitText('text/vtt', false, false);
1262
1262
 
1263
1263
  await mediaSourceEngine.destroy();
1264
1264
  expect(mockTextEngine).toBeTruthy();
@@ -974,9 +974,9 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
974
974
  return [newRefs.shift()];
975
975
  });
976
976
  });
977
- // Wait long enough for all three new refs to be appended.
978
- // Or for all of the new refs to be passed out.
979
- await Promise.race([shaka.test.Util.delay(1), done]);
977
+
978
+ // Wait for the new refs to be appended.
979
+ await done;
980
980
 
981
981
  expect(Array.from(metaIndex)).toEqual(oldRefs.concat(inputRefs2));
982
982
  });
@@ -57,6 +57,9 @@ describe('StreamingEngine', () => {
57
57
  beforeEach(() => {
58
58
  config = shaka.util.PlayerConfiguration.createDefault().streaming;
59
59
 
60
+ // Disable stall detection, which can interfere with playback tests.
61
+ config.stallEnabled = false;
62
+
60
63
  onError = jasmine.createSpy('onError');
61
64
  onError.and.callFake(fail);
62
65
  onEvent = jasmine.createSpy('onEvent');
@@ -276,7 +279,7 @@ describe('StreamingEngine', () => {
276
279
  // Let's go!
277
280
  streamingEngine.switchVariant(variant);
278
281
  await streamingEngine.start();
279
- video.play();
282
+ await video.play();
280
283
  // The overall test timeout is 120 seconds, and the content is 40
281
284
  // seconds. It should be possible to complete this test in 100 seconds,
282
285
  // and if not, we want the error thrown to be within the overall test's
@@ -296,7 +299,7 @@ describe('StreamingEngine', () => {
296
299
  // Let's go!
297
300
  streamingEngine.switchVariant(variant);
298
301
  await streamingEngine.start();
299
- video.play();
302
+ await video.play();
300
303
 
301
304
  // Wait for playback to begin before increasing the playback rate. This
302
305
  // improves test reliability on slow platforms like Chromecast.
@@ -310,7 +313,7 @@ describe('StreamingEngine', () => {
310
313
  // Let's go!
311
314
  streamingEngine.switchVariant(variant);
312
315
  await streamingEngine.start();
313
- video.play();
316
+ await video.play();
314
317
 
315
318
  // After 35 seconds seek back 10 seconds into the first Period.
316
319
  await waiter.timeoutAfter(80).waitUntilPlayheadReaches(video, 35);
@@ -322,7 +325,7 @@ describe('StreamingEngine', () => {
322
325
  // Let's go!
323
326
  streamingEngine.switchVariant(variant);
324
327
  await streamingEngine.start();
325
- video.play();
328
+ await video.play();
326
329
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 20);
327
330
  video.currentTime = 40;
328
331
  await waiter.timeoutAfter(60).waitForEnd(video);
@@ -350,7 +353,7 @@ describe('StreamingEngine', () => {
350
353
  streamingEngine.switchVariant(variant);
351
354
  await streamingEngine.start();
352
355
 
353
- video.play();
356
+ await video.play();
354
357
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 305);
355
358
 
356
359
  const segmentType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
@@ -370,7 +373,7 @@ describe('StreamingEngine', () => {
370
373
  // Seek outside the availability window right away. The playhead
371
374
  // should adjust the video's current time.
372
375
  video.currentTime = segmentAvailability.end + 120;
373
- video.play();
376
+ await video.play();
374
377
 
375
378
  // Wait until the repositioning is complete so we don't
376
379
  // immediately hit this case.
@@ -395,7 +398,7 @@ describe('StreamingEngine', () => {
395
398
  video.currentTime = segmentAvailability.start - 120;
396
399
  expect(video.currentTime).toBeGreaterThan(0);
397
400
 
398
- video.play();
401
+ await video.play();
399
402
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 305);
400
403
 
401
404
  // We are playing close to the beginning of the availability window.
@@ -423,7 +426,7 @@ describe('StreamingEngine', () => {
423
426
  // Let's go!
424
427
  streamingEngine.switchVariant(variant);
425
428
  await streamingEngine.start();
426
- video.play();
429
+ await video.play();
427
430
 
428
431
  await waiter.timeoutAfter(5).waitUntilPlayheadReaches(video, 0.01);
429
432
  expect(video.buffered.length).toBeGreaterThan(0);
@@ -438,7 +441,7 @@ describe('StreamingEngine', () => {
438
441
  // Let's go!
439
442
  streamingEngine.switchVariant(variant);
440
443
  await streamingEngine.start();
441
- video.play();
444
+ await video.play();
442
445
 
443
446
  await waiter.timeoutAfter(5).waitUntilPlayheadReaches(video, 0.01);
444
447
  expect(video.buffered.length).toBeGreaterThan(0);
@@ -457,7 +460,7 @@ describe('StreamingEngine', () => {
457
460
  await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
458
461
 
459
462
  video.currentTime = 8;
460
- video.play();
463
+ await video.play();
461
464
 
462
465
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
463
466
  // Should be close enough to still have the gap buffered.
@@ -474,7 +477,7 @@ describe('StreamingEngine', () => {
474
477
  await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
475
478
 
476
479
  video.currentTime = 8;
477
- video.play();
480
+ await video.play();
478
481
 
479
482
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
480
483
  // Should be close enough to still have the gap buffered.
@@ -316,6 +316,7 @@ describe('ManifestConverter', () => {
316
316
  audioSamplingRate: null,
317
317
  spatialAudio: false,
318
318
  closedCaptions: null,
319
+ external: false,
319
320
  };
320
321
 
321
322
  return streamDB;
@@ -389,6 +390,7 @@ describe('ManifestConverter', () => {
389
390
  spatialAudio: false,
390
391
  closedCaptions: null,
391
392
  tilesLayout: undefined,
393
+ external: false,
392
394
  };
393
395
  }
394
396
 
@@ -438,6 +440,7 @@ describe('ManifestConverter', () => {
438
440
  spatialAudio: false,
439
441
  closedCaptions: null,
440
442
  tilesLayout: undefined,
443
+ external: false,
441
444
  };
442
445
  }
443
446
 
@@ -486,6 +489,7 @@ describe('ManifestConverter', () => {
486
489
  spatialAudio: false,
487
490
  closedCaptions: null,
488
491
  tilesLayout: undefined,
492
+ external: false,
489
493
  };
490
494
  }
491
495
 
@@ -531,6 +535,7 @@ describe('ManifestConverter', () => {
531
535
  spatialAudio: streamDb.spatialAudio,
532
536
  closedCaptions: streamDb.closedCaptions,
533
537
  tilesLayout: streamDb.tilesLayout,
538
+ external: streamDb.external,
534
539
  };
535
540
 
536
541
  expect(stream).toEqual(expectedStream);
@@ -33,6 +33,9 @@ filterDescribe('Offline', supportsStorage, () => {
33
33
  player = new shaka.Player(video);
34
34
  player.addEventListener('error', fail);
35
35
 
36
+ // Disable stall detection, which can interfere with playback tests.
37
+ player.configure('streaming.stallEnabled', false);
38
+
36
39
  eventManager = new shaka.util.EventManager();
37
40
  waiter = new shaka.test.Waiter(eventManager);
38
41
  waiter.setPlayer(player);
@@ -67,7 +70,7 @@ filterDescribe('Offline', supportsStorage, () => {
67
70
 
68
71
  await player.load(contentUri);
69
72
 
70
- video.play();
73
+ await video.play();
71
74
  await playTo(/* end= */ 3, /* timeout= */ 20);
72
75
  await player.unload();
73
76
  await storage.remove(contentUri);
@@ -103,7 +106,7 @@ filterDescribe('Offline', supportsStorage, () => {
103
106
 
104
107
  await player.load(contentUri);
105
108
 
106
- video.play();
109
+ await video.play();
107
110
  await playTo(/* end= */ 3, /* timeout= */ 20);
108
111
  await player.unload();
109
112
  await storage.remove(contentUri);
@@ -146,7 +149,7 @@ filterDescribe('Offline', supportsStorage, () => {
146
149
 
147
150
  await player.load(contentUri);
148
151
 
149
- video.play();
152
+ await video.play();
150
153
  await playTo(/* end= */ 3, /* timeout= */ 20);
151
154
  await player.unload();
152
155
  await storage.remove(contentUri);
@@ -36,6 +36,24 @@ describe('Player', () => {
36
36
  beforeEach(() => {
37
37
  player = new compiledShaka.Player(video);
38
38
 
39
+ // Make sure we are playing the lowest res available to avoid test flake
40
+ // based on network issues. Note that disabling ABR and setting a low
41
+ // abr.defaultBandwidthEstimate would not be sufficient, because it
42
+ // would only affect the choice of track on the first period. When we
43
+ // cross a period boundary, the default bandwidth estimate will no
44
+ // longer be in effect, and AbrManager may choose higher res tracks for
45
+ // the new period. Using abr.restrictions.maxHeight will let us force
46
+ // AbrManager to the lowest resolution, which is its fallback when these
47
+ // soft restrictions cannot be met.
48
+ player.configure('abr.restrictions.maxHeight', 1);
49
+
50
+ // Make sure that live streams are synced against a good clock.
51
+ player.configure('manifest.dash.clockSyncUri',
52
+ 'https://shaka-player-demo.appspot.com/time.txt');
53
+
54
+ // Disable stall detection, which can interfere with playback tests.
55
+ player.configure('streaming.stallEnabled', false);
56
+
39
57
  // Grab event manager from the uncompiled library:
40
58
  eventManager = new shaka.util.EventManager();
41
59
  waiter = new shaka.test.Waiter(eventManager);
@@ -92,21 +110,6 @@ describe('Player', () => {
92
110
  }
93
111
  }
94
112
 
95
- // Make sure we are playing the lowest res available to avoid test flake
96
- // based on network issues. Note that disabling ABR and setting a low
97
- // abr.defaultBandwidthEstimate would not be sufficient, because it
98
- // would only affect the choice of track on the first period. When we
99
- // cross a period boundary, the default bandwidth estimate will no
100
- // longer be in effect, and AbrManager may choose higher res tracks for
101
- // the new period. Using abr.restrictions.maxHeight will let us force
102
- // AbrManager to the lowest resolution, which is its fallback when these
103
- // soft restrictions cannot be met.
104
- player.configure('abr.restrictions.maxHeight', 1);
105
-
106
- // Make sure that live streams are synced against a good clock.
107
- player.configure('manifest.dash.clockSyncUri',
108
- 'https://shaka-player-demo.appspot.com/time.txt');
109
-
110
113
  // Add asset-specific configuration.
111
114
  player.configure(asset.getConfiguration());
112
115
 
@@ -125,7 +128,7 @@ describe('Player', () => {
125
128
  const isLive = asset.features.includes(Feature.LIVE);
126
129
  expect(player.isLive()).toBe(isLive);
127
130
  }
128
- video.play();
131
+ await video.play();
129
132
 
130
133
  // Wait for the video to start playback. If it takes longer than 20
131
134
  // seconds, fail the test.