shaka-player 4.3.8 → 4.3.9

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 (63) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +11 -0
  2. package/.github/workflows/build-and-test.yaml +8 -0
  3. package/.github/workflows/selenium-lab-tests.yaml +3 -2
  4. package/.github/workflows/update-issues.yaml +1 -0
  5. package/CHANGELOG.md +19 -0
  6. package/dist/deps.js +1 -1
  7. package/dist/locales.js +30 -30
  8. package/dist/shaka-player.compiled.d.ts +2 -2
  9. package/dist/shaka-player.compiled.debug.d.ts +2 -2
  10. package/dist/shaka-player.compiled.debug.js +50 -48
  11. package/dist/shaka-player.compiled.debug.map +3 -3
  12. package/dist/shaka-player.compiled.js +385 -385
  13. package/dist/shaka-player.compiled.map +2 -2
  14. package/dist/shaka-player.ui.d.ts +2 -2
  15. package/dist/shaka-player.ui.debug.d.ts +2 -2
  16. package/dist/shaka-player.ui.debug.js +54 -52
  17. package/dist/shaka-player.ui.debug.map +3 -3
  18. package/dist/shaka-player.ui.js +400 -399
  19. package/dist/shaka-player.ui.map +3 -3
  20. package/docs/tutorials/selenium-grid-config.md +60 -8
  21. package/externs/shaka/manifest.js +5 -1
  22. package/externs/shaka/offline.js +5 -1
  23. package/karma.conf.js +50 -7
  24. package/lib/abr/simple_abr_manager.js +5 -5
  25. package/lib/dash/dash_parser.js +1 -0
  26. package/lib/hls/hls_parser.js +1 -0
  27. package/lib/media/media_source_engine.js +6 -5
  28. package/lib/media/streaming_engine.js +2 -2
  29. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  30. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  31. package/lib/offline/manifest_converter.js +1 -0
  32. package/lib/offline/storage.js +1 -0
  33. package/lib/player.js +9 -5
  34. package/lib/polyfill/orientation.js +34 -7
  35. package/lib/text/vtt_text_parser.js +1 -0
  36. package/lib/util/manifest_parser_utils.js +4 -2
  37. package/lib/util/periods.js +2 -0
  38. package/lib/util/platform.js +14 -0
  39. package/lib/util/stream_utils.js +69 -26
  40. package/package.json +2 -2
  41. package/test/cast/cast_utils_unit.js +4 -1
  42. package/test/hls/hls_parser_unit.js +72 -0
  43. package/test/media/adaptation_set_unit.js +1 -0
  44. package/test/media/drm_engine_integration.js +2 -2
  45. package/test/media/media_source_engine_unit.js +1 -1
  46. package/test/media/segment_index_unit.js +3 -3
  47. package/test/media/streaming_engine_integration.js +14 -11
  48. package/test/offline/manifest_convert_unit.js +5 -0
  49. package/test/offline/offline_integration.js +6 -3
  50. package/test/player_external.js +19 -16
  51. package/test/player_integration.js +35 -48
  52. package/test/player_src_equals_integration.js +9 -5
  53. package/test/test/util/fake_demo_main.js +7 -3
  54. package/test/test/util/layout_tests.js +2 -2
  55. package/test/test/util/manifest_generator.js +2 -0
  56. package/test/test/util/offline_utils.js +1 -0
  57. package/test/test/util/streaming_engine_util.js +3 -0
  58. package/test/test/util/ui_utils.js +9 -2
  59. package/test/test/util/util.js +6 -27
  60. package/test/test/util/waiter.js +73 -3
  61. package/test/ui/ad_ui_unit.js +9 -9
  62. package/test/util/stream_utils_unit.js +46 -0
  63. package/ui/range_element.js +5 -0
@@ -437,48 +437,62 @@ shaka.util.StreamUtils = class {
437
437
  manifest.variants = manifest.variants.filter((variant) => {
438
438
  // See: https://github.com/shaka-project/shaka-player/issues/3860
439
439
  const video = variant.video;
440
+
440
441
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
441
442
  const Capabilities = shaka.media.Capabilities;
443
+ const ManifestParserUtils = shaka.util.ManifestParserUtils;
444
+ const MimeUtils = shaka.util.MimeUtils;
445
+ const StreamUtils = shaka.util.StreamUtils;
446
+
442
447
  if (video) {
443
- let videoCodecs =
444
- shaka.util.StreamUtils.getCorrectVideoCodecs_(video.codecs);
448
+ let videoCodecs = StreamUtils.getCorrectVideoCodecs_(video.codecs);
449
+
445
450
  // For multiplexed streams. Here we must check the audio of the
446
451
  // stream to see if it is compatible.
447
452
  if (video.codecs.includes(',')) {
448
453
  const allCodecs = video.codecs.split(',');
449
- videoCodecs = shaka.util.ManifestParserUtils.guessCodecs(
454
+
455
+ videoCodecs = ManifestParserUtils.guessCodecs(
450
456
  ContentType.VIDEO, allCodecs);
451
- videoCodecs =
452
- shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs);
453
- let audioCodecs = shaka.util.ManifestParserUtils.guessCodecs(
457
+ videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
458
+
459
+ let audioCodecs = ManifestParserUtils.guessCodecs(
454
460
  ContentType.AUDIO, allCodecs);
455
- audioCodecs =
456
- shaka.util.StreamUtils.getCorrectAudioCodecs_(audioCodecs);
457
- const audioFullType = shaka.util.MimeUtils.getFullOrConvertedType(
461
+ audioCodecs = StreamUtils.getCorrectAudioCodecs_(audioCodecs);
462
+
463
+ const audioFullType = MimeUtils.getFullOrConvertedType(
458
464
  video.mimeType, audioCodecs, ContentType.AUDIO);
465
+
459
466
  if (!Capabilities.isTypeSupported(audioFullType)) {
460
467
  return false;
461
468
  }
469
+
462
470
  // Update the codec string with the (possibly) converted codecs.
463
471
  videoCodecs = [videoCodecs, audioCodecs].join(',');
464
472
  }
465
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
473
+
474
+ const fullType = MimeUtils.getFullOrConvertedType(
466
475
  video.mimeType, videoCodecs, ContentType.VIDEO);
476
+
467
477
  if (!Capabilities.isTypeSupported(fullType)) {
468
478
  return false;
469
479
  }
480
+
470
481
  // Update the codec string with the (possibly) converted codecs.
471
482
  video.codecs = videoCodecs;
472
483
  }
484
+
473
485
  const audio = variant.audio;
486
+
474
487
  if (audio) {
475
- const codecs =
476
- shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
477
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
488
+ const codecs = StreamUtils.getCorrectAudioCodecs_(audio.codecs);
489
+ const fullType = MimeUtils.getFullOrConvertedType(
478
490
  audio.mimeType, codecs, ContentType.AUDIO);
491
+
479
492
  if (!Capabilities.isTypeSupported(fullType)) {
480
493
  return false;
481
494
  }
495
+
482
496
  // Update the codec string with the (possibly) converted codecs.
483
497
  audio.codecs = codecs;
484
498
  }
@@ -490,7 +504,7 @@ shaka.util.StreamUtils = class {
490
504
  (video.codecs.includes('avc1.') ||
491
505
  video.codecs.includes('avc3.'))) {
492
506
  shaka.log.debug('Dropping variant - not compatible with platform',
493
- shaka.util.StreamUtils.getVariantSummaryString_(variant));
507
+ StreamUtils.getVariantSummaryString_(variant));
494
508
  return false;
495
509
  }
496
510
 
@@ -500,7 +514,7 @@ shaka.util.StreamUtils = class {
500
514
  // Filter out all unsupported variants.
501
515
  if (!supported) {
502
516
  shaka.log.debug('Dropping variant - not compatible with platform',
503
- shaka.util.StreamUtils.getVariantSummaryString_(variant));
517
+ StreamUtils.getVariantSummaryString_(variant));
504
518
  }
505
519
  return supported;
506
520
  });
@@ -564,7 +578,11 @@ shaka.util.StreamUtils = class {
564
578
  static getDecodingConfigs_(variant, usePersistentLicenses, srcEquals) {
565
579
  const audio = variant.audio;
566
580
  const video = variant.video;
581
+
567
582
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
583
+ const ManifestParserUtils = shaka.util.ManifestParserUtils;
584
+ const MimeUtils = shaka.util.MimeUtils;
585
+ const StreamUtils = shaka.util.StreamUtils;
568
586
 
569
587
  /** @type {!MediaDecodingConfiguration} */
570
588
  const mediaDecodingConfig = {
@@ -573,19 +591,23 @@ shaka.util.StreamUtils = class {
573
591
 
574
592
  if (video) {
575
593
  let videoCodecs = video.codecs;
594
+
576
595
  // For multiplexed streams with audio+video codecs, the config should have
577
596
  // AudioConfiguration and VideoConfiguration.
578
597
  if (video.codecs.includes(',')) {
579
598
  const allCodecs = video.codecs.split(',');
580
- videoCodecs = shaka.util.ManifestParserUtils.guessCodecs(
599
+
600
+ videoCodecs = ManifestParserUtils.guessCodecs(
581
601
  ContentType.VIDEO, allCodecs);
582
- videoCodecs =
583
- shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs);
584
- const audioCodecs = shaka.util.ManifestParserUtils.guessCodecs(
602
+ videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
603
+
604
+ let audioCodecs = ManifestParserUtils.guessCodecs(
585
605
  ContentType.AUDIO, allCodecs);
606
+ audioCodecs = StreamUtils.getCorrectAudioCodecs_(audioCodecs);
586
607
 
587
- const audioFullType = shaka.util.MimeUtils.getFullOrConvertedType(
608
+ const audioFullType = MimeUtils.getFullOrConvertedType(
588
609
  video.mimeType, audioCodecs, ContentType.AUDIO);
610
+
589
611
  mediaDecodingConfig.audio = {
590
612
  contentType: audioFullType,
591
613
  channels: 2,
@@ -594,9 +616,11 @@ shaka.util.StreamUtils = class {
594
616
  spatialRendering: false,
595
617
  };
596
618
  }
597
- videoCodecs = shaka.util.StreamUtils.getCorrectVideoCodecs_(videoCodecs);
598
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
619
+
620
+ videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
621
+ const fullType = MimeUtils.getFullOrConvertedType(
599
622
  video.mimeType, videoCodecs, ContentType.VIDEO);
623
+
600
624
  // VideoConfiguration
601
625
  mediaDecodingConfig.video = {
602
626
  contentType: fullType,
@@ -629,9 +653,8 @@ shaka.util.StreamUtils = class {
629
653
  }
630
654
  }
631
655
  if (audio) {
632
- const codecs =
633
- shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
634
- const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
656
+ const codecs = StreamUtils.getCorrectAudioCodecs_(audio.codecs);
657
+ const fullType = MimeUtils.getFullOrConvertedType(
635
658
  audio.mimeType, codecs, ContentType.AUDIO);
636
659
 
637
660
  // AudioConfiguration
@@ -762,6 +785,20 @@ shaka.util.StreamUtils = class {
762
785
  * @private
763
786
  */
764
787
  static getCorrectAudioCodecs_(codecs) {
788
+ // According to RFC 6381 section 3.3, 'fLaC' is actually the correct
789
+ // codec string. We still need to map it to 'flac', as some browsers
790
+ // currently don't support 'fLaC', while 'flac' is supported by most
791
+ // major browsers.
792
+ // See https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
793
+ if (codecs === 'fLaC') {
794
+ return 'flac';
795
+ }
796
+
797
+ // The same is true for 'Opus'.
798
+ if (codecs === 'Opus') {
799
+ return 'opus';
800
+ }
801
+
765
802
  // Some Tizen devices seem to misreport AC-3 support, but correctly
766
803
  // report EC-3 support. So query EC-3 as a fallback for AC-3.
767
804
  // See https://github.com/shaka-project/shaka-player/issues/2989 for
@@ -1240,6 +1277,9 @@ shaka.util.StreamUtils = class {
1240
1277
  if (textTrack.kind == 'captions') {
1241
1278
  track.mimeType = CLOSED_CAPTION_MIMETYPE;
1242
1279
  }
1280
+ if (textTrack.kind == 'subtitles') {
1281
+ track.mimeType = 'text/vtt';
1282
+ }
1243
1283
  if (textTrack.kind) {
1244
1284
  track.roles = [textTrack.kind];
1245
1285
  }
@@ -1287,13 +1327,15 @@ shaka.util.StreamUtils = class {
1287
1327
  * @private
1288
1328
  */
1289
1329
  static html5TrackToGenericShakaTrack_(html5Track) {
1330
+ const language = html5Track.language;
1331
+
1290
1332
  /** @type {shaka.extern.Track} */
1291
1333
  const track = {
1292
1334
  id: shaka.util.StreamUtils.html5TrackId(html5Track),
1293
1335
  active: false,
1294
1336
  type: '',
1295
1337
  bandwidth: 0,
1296
- language: shaka.util.LanguageUtils.normalize(html5Track.language),
1338
+ language: shaka.util.LanguageUtils.normalize(language || 'und'),
1297
1339
  label: html5Track.label,
1298
1340
  kind: html5Track.kind,
1299
1341
  width: null,
@@ -1323,6 +1365,7 @@ shaka.util.StreamUtils = class {
1323
1365
  originalAudioId: null,
1324
1366
  originalTextId: null,
1325
1367
  originalImageId: null,
1368
+ originalLanguage: language,
1326
1369
  };
1327
1370
 
1328
1371
  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.3.8",
4
+ "version": "4.3.9",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -42,7 +42,7 @@
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} */
@@ -628,6 +628,78 @@ describe('HlsParser', () => {
628
628
  await testHlsParser(master, media, manifest);
629
629
  });
630
630
 
631
+ it('accepts fLaC codec as audio/mp4', async () => {
632
+ const master = [
633
+ '#EXTM3U\n',
634
+ '#EXT-X-STREAM-INF:BANDWIDTH=1000000,CODECS="fLaC"\n',
635
+ 'audio\n',
636
+ '#EXT-X-STREAM-INF:BANDWIDTH=1000000,CODECS="flac"\n',
637
+ 'audio2\n',
638
+ ].join('');
639
+
640
+ const media = [
641
+ '#EXTM3U\n',
642
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
643
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
644
+ '#EXTINF:5,\n',
645
+ '#EXT-X-BYTERANGE:121090@616\n',
646
+ 'main.mp4',
647
+ ].join('');
648
+
649
+ const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
650
+ manifest.anyTimeline();
651
+ manifest.addPartialVariant((variant) => {
652
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
653
+ stream.mime('audio/mp4', 'fLaC');
654
+ });
655
+ });
656
+ manifest.addPartialVariant((variant) => {
657
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
658
+ stream.mime('audio/mp4', 'flac');
659
+ });
660
+ });
661
+ manifest.sequenceMode = true;
662
+ });
663
+
664
+ await testHlsParser(master, media, manifest);
665
+ });
666
+
667
+ it('accepts Opus codec as audio/mp4', async () => {
668
+ const master = [
669
+ '#EXTM3U\n',
670
+ '#EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS="Opus"\n',
671
+ 'audio\n',
672
+ '#EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS="opus"\n',
673
+ 'audio2\n',
674
+ ].join('');
675
+
676
+ const media = [
677
+ '#EXTM3U\n',
678
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
679
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
680
+ '#EXTINF:5,\n',
681
+ '#EXT-X-BYTERANGE:121090@616\n',
682
+ 'main.mp4',
683
+ ].join('');
684
+
685
+ const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
686
+ manifest.anyTimeline();
687
+ manifest.addPartialVariant((variant) => {
688
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
689
+ stream.mime('audio/mp4', 'Opus');
690
+ });
691
+ });
692
+ manifest.addPartialVariant((variant) => {
693
+ variant.addPartialStream(ContentType.AUDIO, (stream) => {
694
+ stream.mime('audio/mp4', 'opus');
695
+ });
696
+ });
697
+ manifest.sequenceMode = true;
698
+ });
699
+
700
+ await testHlsParser(master, media, manifest);
701
+ });
702
+
631
703
  it('parses audio+video variant with closed captions', async () => {
632
704
  const master = [
633
705
  '#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
  });
@@ -244,7 +244,7 @@ describe('DrmEngine', () => {
244
244
  /* hasClosedCaptions= */ false);
245
245
 
246
246
  expect(video.buffered.end(0)).toBeGreaterThan(0);
247
- video.play();
247
+ await video.play();
248
248
 
249
249
  const waiter = new shaka.test.Waiter(eventManager).timeoutAfter(15);
250
250
  waiter.setMediaSourceEngine(mediaSourceEngine);
@@ -327,7 +327,7 @@ describe('DrmEngine', () => {
327
327
  /* hasClosedCaptions= */ false);
328
328
 
329
329
  expect(video.buffered.end(0)).toBeGreaterThan(0);
330
- video.play();
330
+ await video.play();
331
331
 
332
332
  const waiter = new shaka.test.Waiter(eventManager).timeoutAfter(15);
333
333
  waiter.setMediaSourceEngine(mediaSourceEngine);
@@ -1262,7 +1262,7 @@ describe('MediaSourceEngine', () => {
1262
1262
  });
1263
1263
 
1264
1264
  it('destroys text engines', async () => {
1265
- mediaSourceEngine.reinitText('text/vtt', false);
1265
+ mediaSourceEngine.reinitText('text/vtt', false, false);
1266
1266
 
1267
1267
  await mediaSourceEngine.destroy();
1268
1268
  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');
@@ -279,7 +282,7 @@ describe('StreamingEngine', () => {
279
282
  // Let's go!
280
283
  streamingEngine.switchVariant(variant);
281
284
  await streamingEngine.start();
282
- video.play();
285
+ await video.play();
283
286
  // The overall test timeout is 120 seconds, and the content is 40
284
287
  // seconds. It should be possible to complete this test in 100 seconds,
285
288
  // and if not, we want the error thrown to be within the overall test's
@@ -299,7 +302,7 @@ describe('StreamingEngine', () => {
299
302
  // Let's go!
300
303
  streamingEngine.switchVariant(variant);
301
304
  await streamingEngine.start();
302
- video.play();
305
+ await video.play();
303
306
 
304
307
  // Wait for playback to begin before increasing the playback rate. This
305
308
  // improves test reliability on slow platforms like Chromecast.
@@ -313,7 +316,7 @@ describe('StreamingEngine', () => {
313
316
  // Let's go!
314
317
  streamingEngine.switchVariant(variant);
315
318
  await streamingEngine.start();
316
- video.play();
319
+ await video.play();
317
320
 
318
321
  // After 35 seconds seek back 10 seconds into the first Period.
319
322
  await waiter.timeoutAfter(80).waitUntilPlayheadReaches(video, 35);
@@ -325,7 +328,7 @@ describe('StreamingEngine', () => {
325
328
  // Let's go!
326
329
  streamingEngine.switchVariant(variant);
327
330
  await streamingEngine.start();
328
- video.play();
331
+ await video.play();
329
332
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 20);
330
333
  video.currentTime = 40;
331
334
  await waiter.timeoutAfter(60).waitForEnd(video);
@@ -353,7 +356,7 @@ describe('StreamingEngine', () => {
353
356
  streamingEngine.switchVariant(variant);
354
357
  await streamingEngine.start();
355
358
 
356
- video.play();
359
+ await video.play();
357
360
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 305);
358
361
 
359
362
  const segmentType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
@@ -373,7 +376,7 @@ describe('StreamingEngine', () => {
373
376
  // Seek outside the availability window right away. The playhead
374
377
  // should adjust the video's current time.
375
378
  video.currentTime = segmentAvailability.end + 120;
376
- video.play();
379
+ await video.play();
377
380
 
378
381
  // Wait until the repositioning is complete so we don't
379
382
  // immediately hit this case.
@@ -398,7 +401,7 @@ describe('StreamingEngine', () => {
398
401
  video.currentTime = segmentAvailability.start - 120;
399
402
  expect(video.currentTime).toBeGreaterThan(0);
400
403
 
401
- video.play();
404
+ await video.play();
402
405
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 305);
403
406
 
404
407
  // We are playing close to the beginning of the availability window.
@@ -426,7 +429,7 @@ describe('StreamingEngine', () => {
426
429
  // Let's go!
427
430
  streamingEngine.switchVariant(variant);
428
431
  await streamingEngine.start();
429
- video.play();
432
+ await video.play();
430
433
 
431
434
  await waiter.timeoutAfter(5).waitUntilPlayheadReaches(video, 0.01);
432
435
  expect(video.buffered.length).toBeGreaterThan(0);
@@ -441,7 +444,7 @@ describe('StreamingEngine', () => {
441
444
  // Let's go!
442
445
  streamingEngine.switchVariant(variant);
443
446
  await streamingEngine.start();
444
- video.play();
447
+ await video.play();
445
448
 
446
449
  await waiter.timeoutAfter(5).waitUntilPlayheadReaches(video, 0.01);
447
450
  expect(video.buffered.length).toBeGreaterThan(0);
@@ -460,7 +463,7 @@ describe('StreamingEngine', () => {
460
463
  await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
461
464
 
462
465
  video.currentTime = 8;
463
- video.play();
466
+ await video.play();
464
467
 
465
468
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
466
469
  // Should be close enough to still have the gap buffered.
@@ -477,7 +480,7 @@ describe('StreamingEngine', () => {
477
480
  await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
478
481
 
479
482
  video.currentTime = 8;
480
- video.play();
483
+ await video.play();
481
484
 
482
485
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
483
486
  // 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.