rx-player 4.0.0-beta.0 → 4.0.0-beta.2
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.
- package/.eslintrc.js +8 -0
- package/CHANGELOG.md +93 -0
- package/CONTRIBUTING.md +48 -168
- package/FILES.md +40 -92
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +25 -12
- package/dist/_esm5.processed/compat/browser_detection.js +85 -38
- package/dist/_esm5.processed/compat/can_reuse_media_keys.js +2 -2
- package/dist/_esm5.processed/compat/eme/close_session.js +2 -2
- package/dist/_esm5.processed/compat/eme/load_session.js +1 -1
- package/dist/_esm5.processed/compat/event_listeners.js +1 -1
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
- package/dist/_esm5.processed/config.d.ts +4 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +9 -6
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
- package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
- package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
- package/dist/_esm5.processed/core/api/debug/buffer_graph.d.ts +28 -0
- package/dist/_esm5.processed/core/api/debug/buffer_graph.js +175 -0
- package/dist/_esm5.processed/core/api/debug/buffer_size_graph.d.ts +10 -0
- package/dist/_esm5.processed/core/api/debug/buffer_size_graph.js +104 -0
- package/dist/_esm5.processed/core/api/debug/constants.d.ts +2 -0
- package/dist/_esm5.processed/core/api/debug/constants.js +2 -0
- package/dist/_esm5.processed/core/api/debug/index.d.ts +2 -0
- package/dist/_esm5.processed/core/api/debug/index.js +2 -0
- package/dist/_esm5.processed/core/api/debug/modules/general_info.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/modules/general_info.js +180 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.d.ts +4 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.js +121 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.js +35 -0
- package/dist/_esm5.processed/core/api/debug/render.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/render.js +32 -0
- package/dist/_esm5.processed/core/api/debug/utils.d.ts +39 -0
- package/dist/_esm5.processed/core/api/debug/utils.js +57 -0
- package/dist/_esm5.processed/core/api/playback_observer.js +4 -2
- package/dist/_esm5.processed/core/api/public_api.d.ts +60 -3
- package/dist/_esm5.processed/core/api/public_api.js +280 -60
- package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
- package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
- package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
- package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
- package/dist/_esm5.processed/core/api/utils.js +23 -3
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.d.ts +27 -8
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.js +28 -7
- package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -1
- package/dist/_esm5.processed/core/decrypt/content_decryptor.js +1 -1
- package/dist/_esm5.processed/core/decrypt/find_key_system.js +29 -6
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +42 -32
- package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +4 -0
- package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +17 -8
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +10 -6
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +5 -4
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +22 -5
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +37 -21
- package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +21 -23
- package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +17 -7
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +2 -2
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +74 -41
- package/dist/_esm5.processed/core/init/types.d.ts +9 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +24 -11
- package/dist/_esm5.processed/core/init/utils/create_media_source.js +3 -12
- package/dist/_esm5.processed/core/init/utils/end_of_stream.js +6 -3
- package/dist/_esm5.processed/core/init/utils/get_loaded_reference.js +2 -1
- package/dist/_esm5.processed/core/init/utils/initial_seek_and_play.js +9 -5
- package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -1
- package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
- package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +87 -86
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +83 -3
- package/dist/_esm5.processed/core/init/utils/stream_events_emitter/stream_events_emitter.js +6 -4
- package/dist/_esm5.processed/core/init/utils/throw_on_media_error.js +1 -1
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +38 -50
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +16 -2
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
- package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +13 -9
- package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +30 -16
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +41 -20
- package/dist/_esm5.processed/core/stream/period/period_stream.js +12 -11
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +37 -28
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +3 -3
- package/dist/_esm5.processed/core/stream/representation/utils/downloading_queue.js +16 -6
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.d.ts +3 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
- package/dist/_esm5.processed/core/stream/utils/create_reload_request.js +1 -1
- package/dist/_esm5.processed/default_config.d.ts +41 -0
- package/dist/_esm5.processed/default_config.js +46 -2
- package/dist/_esm5.processed/errors/index.d.ts +2 -2
- package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
- package/dist/_esm5.processed/errors/media_error.js +18 -5
- package/dist/_esm5.processed/experimental/features/debug_element.d.ts +8 -0
- package/dist/_esm5.processed/experimental/features/debug_element.js +10 -0
- package/dist/_esm5.processed/experimental/features/index.d.ts +1 -0
- package/dist/_esm5.processed/experimental/features/index.js +1 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +7 -4
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +24 -12
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
- package/dist/_esm5.processed/features/features_object.js +1 -0
- package/dist/_esm5.processed/features/initialize_features.js +13 -10
- package/dist/_esm5.processed/features/types.d.ts +3 -0
- package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
- package/dist/_esm5.processed/manifest/adaptation.js +80 -1
- package/dist/_esm5.processed/manifest/manifest.js +2 -0
- package/dist/_esm5.processed/manifest/period.js +2 -2
- package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
- package/dist/_esm5.processed/manifest/representation.js +32 -4
- package/dist/_esm5.processed/manifest/utils.js +1 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.js +105 -137
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +25 -5
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
- package/dist/_esm5.processed/public_types.d.ts +13 -3
- package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
- package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +15 -11
- package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +2 -2
- package/dist/_esm5.processed/transports/dash/manifest_parser.js +1 -1
- package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -4
- package/dist/_esm5.processed/transports/local/segment_loader.js +13 -26
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
- package/dist/_esm5.processed/transports/smooth/segment_loader.js +4 -4
- package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
- package/dist/_esm5.processed/utils/cancellable_sleep.js +4 -10
- package/dist/_esm5.processed/utils/create_cancellable_promise.d.ts +26 -0
- package/dist/_esm5.processed/utils/create_cancellable_promise.js +52 -0
- package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
- package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
- package/dist/_esm5.processed/utils/reference.js +6 -0
- package/dist/_esm5.processed/utils/request/xhr.js +1 -1
- package/dist/_esm5.processed/utils/task_canceller.d.ts +34 -15
- package/dist/_esm5.processed/utils/task_canceller.js +55 -22
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +5424 -4712
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +1 -5
- package/package.json +44 -40
- package/scripts/build/constants.d.ts +1 -0
- package/scripts/build/generate_build.js +1 -1
- package/scripts/fast_demo_build.js +40 -40
- package/scripts/generate_full_demo.js +1 -1
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +105 -52
- package/src/compat/can_reuse_media_keys.ts +5 -2
- package/src/compat/eme/close_session.ts +2 -2
- package/src/compat/eme/load_session.ts +1 -1
- package/src/compat/event_listeners.ts +1 -1
- package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
- package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
- package/src/core/adaptive/adaptive_representation_selector.ts +11 -6
- package/src/core/adaptive/buffer_based_chooser.ts +144 -26
- package/src/core/adaptive/guess_based_chooser.ts +9 -8
- package/src/core/adaptive/network_analyzer.ts +9 -4
- package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
- package/src/core/api/debug/buffer_graph.ts +247 -0
- package/src/core/api/debug/buffer_size_graph.ts +130 -0
- package/src/core/api/debug/constants.ts +2 -0
- package/src/core/api/debug/index.ts +3 -0
- package/src/core/api/debug/modules/general_info.ts +184 -0
- package/src/core/api/debug/modules/segment_buffer_content.ts +155 -0
- package/src/core/api/debug/modules/segment_buffer_size.ts +48 -0
- package/src/core/api/debug/render.ts +40 -0
- package/src/core/api/debug/utils.ts +103 -0
- package/src/core/api/playback_observer.ts +5 -2
- package/src/core/api/public_api.ts +334 -73
- package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
- package/src/core/api/track_management/track_dispatcher.ts +37 -14
- package/src/core/api/track_management/tracks_store.ts +77 -167
- package/src/core/api/utils.ts +29 -3
- package/src/core/decrypt/__tests__/__global__/utils.ts +61 -40
- package/src/core/decrypt/attach_media_keys.ts +1 -1
- package/src/core/decrypt/content_decryptor.ts +1 -1
- package/src/core/decrypt/find_key_system.ts +25 -11
- package/src/core/decrypt/session_events_listener.ts +45 -39
- package/src/core/decrypt/utils/check_key_statuses.ts +6 -0
- package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
- package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
- package/src/core/fetchers/cdn_prioritizer.ts +18 -9
- package/src/core/fetchers/manifest/manifest_fetcher.ts +5 -4
- package/src/core/fetchers/segment/segment_fetcher.ts +36 -14
- package/src/core/fetchers/segment/task_prioritizer.ts +25 -30
- package/src/core/fetchers/utils/schedule_request.ts +18 -7
- package/src/core/init/directfile_content_initializer.ts +2 -1
- package/src/core/init/media_source_content_initializer.ts +89 -50
- package/src/core/init/types.ts +9 -1
- package/src/core/init/utils/content_time_boundaries_observer.ts +48 -12
- package/src/core/init/utils/create_media_source.ts +4 -16
- package/src/core/init/utils/end_of_stream.ts +6 -3
- package/src/core/init/utils/get_loaded_reference.ts +2 -1
- package/src/core/init/utils/initial_seek_and_play.ts +9 -5
- package/src/core/init/utils/initialize_content_decryption.ts +2 -1
- package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +103 -110
- package/src/core/init/utils/rebuffering_controller.ts +115 -4
- package/src/core/init/utils/stream_events_emitter/stream_events_emitter.ts +6 -4
- package/src/core/init/utils/throw_on_media_error.ts +1 -1
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +63 -66
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +20 -2
- package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/types.ts +16 -4
- package/src/core/segment_buffers/index.ts +2 -0
- package/src/core/segment_buffers/segment_buffers_store.ts +16 -13
- package/src/core/stream/adaptation/adaptation_stream.ts +33 -19
- package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
- package/src/core/stream/orchestrator/stream_orchestrator.ts +42 -20
- package/src/core/stream/period/period_stream.ts +13 -11
- package/src/core/stream/representation/representation_stream.ts +49 -37
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +9 -4
- package/src/core/stream/representation/utils/downloading_queue.ts +16 -4
- package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
- package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
- package/src/core/stream/utils/create_reload_request.ts +1 -1
- package/src/default_config.ts +59 -11
- package/src/errors/__tests__/media_error.test.ts +6 -6
- package/src/errors/index.ts +4 -1
- package/src/errors/media_error.ts +67 -1
- package/src/experimental/features/__tests__/debug_element.test.ts +26 -0
- package/src/experimental/features/debug_element.ts +13 -0
- package/src/experimental/features/index.ts +1 -0
- package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
- package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +7 -4
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +25 -10
- package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
- package/src/features/__tests__/initialize_features.test.ts +11 -0
- package/src/features/features_object.ts +1 -0
- package/src/features/initialize_features.ts +15 -10
- package/src/features/types.ts +9 -0
- package/src/manifest/__tests__/manifest.test.ts +7 -7
- package/src/manifest/__tests__/period.test.ts +90 -45
- package/src/manifest/adaptation.ts +96 -1
- package/src/manifest/manifest.ts +4 -0
- package/src/manifest/period.ts +4 -2
- package/src/manifest/representation.ts +77 -5
- package/src/manifest/utils.ts +1 -3
- package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +116 -151
- package/src/parsers/manifest/dash/common/parse_representations.ts +21 -4
- package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
- package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
- package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
- package/src/public_types.ts +16 -1
- package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
- package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +31 -22
- package/src/transports/dash/low_latency_segment_loader.ts +2 -2
- package/src/transports/dash/manifest_parser.ts +1 -1
- package/src/transports/dash/segment_loader.ts +4 -4
- package/src/transports/local/segment_loader.ts +14 -30
- package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
- package/src/transports/smooth/segment_loader.ts +4 -4
- package/src/transports/utils/call_custom_manifest_loader.ts +3 -3
- package/src/typings/globals.d.ts +21 -19
- package/src/utils/cancellable_sleep.ts +5 -14
- package/src/utils/create_cancellable_promise.ts +69 -0
- package/src/utils/is_null_or_undefined.ts +1 -1
- package/src/utils/reference.ts +6 -0
- package/src/utils/request/xhr.ts +1 -1
- package/src/utils/task_canceller.ts +63 -34
- package/tsconfig.json +1 -1
- package/tsconfig.modules.json +1 -1
- package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
- package/locked_reps.js +0 -46
- package/scripts/doc-generator/construct_table_of_contents.js +0 -76
- package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
- package/scripts/doc-generator/create_documentation.js +0 -331
- package/scripts/doc-generator/create_documentation_page.js +0 -209
- package/scripts/doc-generator/create_page.js +0 -210
- package/scripts/doc-generator/generate_header_html.js +0 -147
- package/scripts/doc-generator/generate_page_html.js +0 -115
- package/scripts/doc-generator/generate_page_list_html.js +0 -92
- package/scripts/doc-generator/generate_sidebar_html.js +0 -85
- package/scripts/doc-generator/get_search_data_for_content.js +0 -137
- package/scripts/doc-generator/index.js +0 -34
- package/scripts/doc-generator/parse_doc_configs.js +0 -327
- package/scripts/doc-generator/scripts/lunr.js +0 -10
- package/scripts/doc-generator/scripts/script.js +0 -451
- package/scripts/doc-generator/styles/code.css +0 -99
- package/scripts/doc-generator/styles/style.css +0 -835
- package/scripts/doc-generator/utils.js +0 -74
|
@@ -162,6 +162,13 @@ function estimateStarvationModeBitrate(
|
|
|
162
162
|
|
|
163
163
|
const concernedRequest = concernedRequests[0];
|
|
164
164
|
const now = performance.now();
|
|
165
|
+
|
|
166
|
+
let minimumRequestTime = concernedRequest.content.segment.duration * 1.5;
|
|
167
|
+
minimumRequestTime = Math.min(minimumRequestTime, 3000);
|
|
168
|
+
minimumRequestTime = Math.max(minimumRequestTime, 12000);
|
|
169
|
+
if (now - concernedRequest.requestTimestamp < minimumRequestTime) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
165
172
|
const lastProgressEvent = concernedRequest.progress.length > 0 ?
|
|
166
173
|
concernedRequest.progress[concernedRequest.progress.length - 1] :
|
|
167
174
|
undefined;
|
|
@@ -178,7 +185,7 @@ function estimateStarvationModeBitrate(
|
|
|
178
185
|
// Calculate estimated time spent rebuffering if we continue doing that request.
|
|
179
186
|
const expectedRebufferingTime = remainingTime -
|
|
180
187
|
(realBufferGap / speed);
|
|
181
|
-
if (expectedRebufferingTime >
|
|
188
|
+
if (expectedRebufferingTime > 2500) {
|
|
182
189
|
return bandwidthEstimate;
|
|
183
190
|
}
|
|
184
191
|
}
|
|
@@ -402,10 +409,8 @@ export default class NetworkAnalyzer {
|
|
|
402
409
|
) : boolean {
|
|
403
410
|
if (currentRepresentation === null) {
|
|
404
411
|
return true;
|
|
405
|
-
} else if (bitrate
|
|
412
|
+
} else if (bitrate >= currentRepresentation.bitrate) {
|
|
406
413
|
return false;
|
|
407
|
-
} else if (bitrate > currentRepresentation.bitrate) {
|
|
408
|
-
return !this._inStarvationMode;
|
|
409
414
|
}
|
|
410
415
|
return shouldDirectlySwitchToLowBitrate(playbackInfo,
|
|
411
416
|
currentRequests,
|
|
@@ -18,6 +18,26 @@ import log from "../../../log";
|
|
|
18
18
|
import { Representation } from "../../../manifest";
|
|
19
19
|
import EWMA from "./ewma";
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Object representing a maintainability score as calculated by the
|
|
23
|
+
* `RepresentationScoreCalculator`.
|
|
24
|
+
*/
|
|
25
|
+
export interface IRepresentationMaintainabilityScore {
|
|
26
|
+
/**
|
|
27
|
+
* Weighted mean of dividing the loaded segment's duration by the time to make
|
|
28
|
+
* their request.
|
|
29
|
+
*/
|
|
30
|
+
score : number;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The confidence we have on the calculated `score` in reflecting a useful
|
|
34
|
+
* maintainability hint for the concerned Representation.
|
|
35
|
+
*
|
|
36
|
+
* Basically, the more segments have been loaded, the higher the confidence.
|
|
37
|
+
*/
|
|
38
|
+
confidenceLevel: ScoreConfidenceLevel;
|
|
39
|
+
}
|
|
40
|
+
|
|
21
41
|
/**
|
|
22
42
|
* Calculate the "maintainability score" of a given Representation:
|
|
23
43
|
* - A score higher than 1 means that the Representation can theorically
|
|
@@ -107,7 +127,7 @@ export default class RepresentationScoreCalculator {
|
|
|
107
127
|
*/
|
|
108
128
|
public getEstimate(
|
|
109
129
|
representation : Representation
|
|
110
|
-
) :
|
|
130
|
+
) : IRepresentationMaintainabilityScore | undefined {
|
|
111
131
|
if (this._currentRepresentationData === null ||
|
|
112
132
|
this._currentRepresentationData.representation.id !== representation.id)
|
|
113
133
|
{
|
|
@@ -119,7 +139,7 @@ export default class RepresentationScoreCalculator {
|
|
|
119
139
|
loadedDuration >= 10 ? ScoreConfidenceLevel.HIGH :
|
|
120
140
|
ScoreConfidenceLevel.LOW;
|
|
121
141
|
|
|
122
|
-
return
|
|
142
|
+
return { score: estimate, confidenceLevel };
|
|
123
143
|
}
|
|
124
144
|
|
|
125
145
|
/**
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { Representation } from "../../../manifest";
|
|
2
|
+
import { IBufferedChunk } from "../../segment_buffers";
|
|
3
|
+
|
|
4
|
+
const BUFFER_WIDTH_IN_SECONDS = 10000;
|
|
5
|
+
|
|
6
|
+
const COLORS = [
|
|
7
|
+
"#2ab7ca",
|
|
8
|
+
"#fed766",
|
|
9
|
+
"#4dd248",
|
|
10
|
+
"#a22c28",
|
|
11
|
+
"#556b2f", // darkolivegreen
|
|
12
|
+
"#add8e6", // lightblue
|
|
13
|
+
"#90ee90", // lightgreen
|
|
14
|
+
"#444444",
|
|
15
|
+
"#40bfc1",
|
|
16
|
+
"#57557e",
|
|
17
|
+
"#fbe555",
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export interface ISegmentBufferGrapUpdateData {
|
|
21
|
+
currentTime : number;
|
|
22
|
+
inventory : IBufferedChunk[];
|
|
23
|
+
width : number;
|
|
24
|
+
height : number;
|
|
25
|
+
minimumPosition : number | undefined;
|
|
26
|
+
maximumPosition : number | undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default class SegmentBufferGraph {
|
|
30
|
+
/** Link buffered Representation to their corresponding color. */
|
|
31
|
+
private readonly _colorMap : WeakMap<Representation, string>;
|
|
32
|
+
|
|
33
|
+
/** Current amount of colors chosen to represent the various Representation. */
|
|
34
|
+
private _currNbColors : number;
|
|
35
|
+
|
|
36
|
+
/** Canvas that will contain the buffer graph itself. */
|
|
37
|
+
private readonly _canvasElt : HTMLCanvasElement;
|
|
38
|
+
|
|
39
|
+
private readonly _canvasCtxt : CanvasRenderingContext2D | null;
|
|
40
|
+
|
|
41
|
+
constructor(canvasElt : HTMLCanvasElement) {
|
|
42
|
+
this._colorMap = new WeakMap();
|
|
43
|
+
this._currNbColors = 0;
|
|
44
|
+
this._canvasElt = canvasElt;
|
|
45
|
+
this._canvasCtxt = this._canvasElt.getContext("2d");
|
|
46
|
+
this.clear();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public clear() {
|
|
50
|
+
if (this._canvasCtxt !== null) {
|
|
51
|
+
this._canvasCtxt.clearRect(0, 0, this._canvasElt.width, this._canvasElt.height);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public update(data : ISegmentBufferGrapUpdateData) : void {
|
|
56
|
+
if (this._canvasCtxt === null) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const {
|
|
60
|
+
inventory,
|
|
61
|
+
currentTime,
|
|
62
|
+
width,
|
|
63
|
+
height,
|
|
64
|
+
} = data;
|
|
65
|
+
this._canvasElt.style.width = `${width}px`;
|
|
66
|
+
this._canvasElt.style.height = `${height}px`;
|
|
67
|
+
this._canvasElt.width = width;
|
|
68
|
+
this._canvasElt.height = height;
|
|
69
|
+
this.clear();
|
|
70
|
+
let minimumPoint : number;
|
|
71
|
+
if (data.minimumPosition !== undefined) {
|
|
72
|
+
if (inventory.length > 0) {
|
|
73
|
+
minimumPoint = Math.min(data.minimumPosition, inventory[0].start);
|
|
74
|
+
} else {
|
|
75
|
+
minimumPoint = data.minimumPosition;
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
minimumPoint = inventory[0]?.start ?? 0;
|
|
79
|
+
}
|
|
80
|
+
let maximumPoint : number;
|
|
81
|
+
if (data.maximumPosition !== undefined) {
|
|
82
|
+
if (inventory.length > 0) {
|
|
83
|
+
maximumPoint = Math.max(data.maximumPosition,
|
|
84
|
+
inventory[inventory.length - 1].end);
|
|
85
|
+
} else {
|
|
86
|
+
maximumPoint = data.maximumPosition;
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
maximumPoint = inventory[inventory.length - 1]?.end ??
|
|
90
|
+
1000;
|
|
91
|
+
}
|
|
92
|
+
minimumPoint = Math.min(currentTime, minimumPoint);
|
|
93
|
+
maximumPoint = Math.max(currentTime, maximumPoint);
|
|
94
|
+
|
|
95
|
+
let minimumPosition;
|
|
96
|
+
let maximumPosition;
|
|
97
|
+
if (maximumPoint - minimumPoint > BUFFER_WIDTH_IN_SECONDS) {
|
|
98
|
+
if (currentTime === undefined) {
|
|
99
|
+
minimumPosition = minimumPoint;
|
|
100
|
+
maximumPosition = maximumPoint;
|
|
101
|
+
} else if (maximumPoint - currentTime < BUFFER_WIDTH_IN_SECONDS / 2) {
|
|
102
|
+
maximumPosition = maximumPoint;
|
|
103
|
+
minimumPosition = maximumPoint - BUFFER_WIDTH_IN_SECONDS;
|
|
104
|
+
} else if (currentTime - minimumPoint < BUFFER_WIDTH_IN_SECONDS / 2) {
|
|
105
|
+
minimumPosition = minimumPoint;
|
|
106
|
+
maximumPosition = minimumPoint + BUFFER_WIDTH_IN_SECONDS;
|
|
107
|
+
} else {
|
|
108
|
+
minimumPosition = currentTime - BUFFER_WIDTH_IN_SECONDS / 2;
|
|
109
|
+
maximumPosition = currentTime + BUFFER_WIDTH_IN_SECONDS / 2;
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
minimumPosition = minimumPoint;
|
|
113
|
+
maximumPosition = maximumPoint;
|
|
114
|
+
}
|
|
115
|
+
if (minimumPosition >= maximumPosition) {
|
|
116
|
+
this.clear();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const currentRangesScaled = scaleSegments(inventory,
|
|
121
|
+
minimumPosition,
|
|
122
|
+
maximumPosition);
|
|
123
|
+
|
|
124
|
+
for (let i = 0; i < currentRangesScaled.length; i++) {
|
|
125
|
+
this._paintRange(currentRangesScaled[i], width, height);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (currentTime !== undefined) {
|
|
129
|
+
paintCurrentPosition(currentTime,
|
|
130
|
+
minimumPosition,
|
|
131
|
+
maximumPosition,
|
|
132
|
+
this._canvasCtxt,
|
|
133
|
+
width,
|
|
134
|
+
height);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Paint a given range in the canvas
|
|
140
|
+
* @param {Object} rangeScaled - Buffered segment information with added
|
|
141
|
+
* "scaling" information to know where it fits in the canvas.
|
|
142
|
+
*/
|
|
143
|
+
private _paintRange(
|
|
144
|
+
rangeScaled : IScaledChunk,
|
|
145
|
+
width : number,
|
|
146
|
+
height : number
|
|
147
|
+
) : void {
|
|
148
|
+
if (this._canvasCtxt === null) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const startX = rangeScaled.scaledStart * width;
|
|
152
|
+
const endX = rangeScaled.scaledEnd * width;
|
|
153
|
+
this._canvasCtxt.fillStyle = this._getColorForRepresentation(
|
|
154
|
+
rangeScaled.info.infos.representation
|
|
155
|
+
);
|
|
156
|
+
this._canvasCtxt.fillRect(
|
|
157
|
+
Math.ceil(startX),
|
|
158
|
+
0,
|
|
159
|
+
Math.ceil(endX - startX),
|
|
160
|
+
height
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private _getColorForRepresentation(
|
|
165
|
+
representation : Representation
|
|
166
|
+
) : string {
|
|
167
|
+
const color = this._colorMap.get(representation);
|
|
168
|
+
if (color !== undefined) {
|
|
169
|
+
return color;
|
|
170
|
+
}
|
|
171
|
+
const newColor = COLORS[this._currNbColors % COLORS.length];
|
|
172
|
+
this._currNbColors++;
|
|
173
|
+
this._colorMap.set(representation, newColor);
|
|
174
|
+
return newColor;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Represent the current position in the canvas.
|
|
180
|
+
* @param {number|undefined} position - The current position
|
|
181
|
+
* @param {number} minimumPosition - minimum possible position represented in
|
|
182
|
+
* the canvas.
|
|
183
|
+
* @param {number} maximumPosition - maximum possible position represented in
|
|
184
|
+
* the canvas.
|
|
185
|
+
* @param {Object} canvasCtx - The canvas' 2D context
|
|
186
|
+
*/
|
|
187
|
+
function paintCurrentPosition(
|
|
188
|
+
position : number,
|
|
189
|
+
minimumPosition : number,
|
|
190
|
+
maximumPosition : number,
|
|
191
|
+
canvasCtx : CanvasRenderingContext2D,
|
|
192
|
+
width : number,
|
|
193
|
+
height : number
|
|
194
|
+
) {
|
|
195
|
+
if (typeof position === "number" &&
|
|
196
|
+
position >= minimumPosition &&
|
|
197
|
+
position < maximumPosition)
|
|
198
|
+
{
|
|
199
|
+
const lengthCanvas = maximumPosition - minimumPosition;
|
|
200
|
+
canvasCtx.fillStyle = "#FF0000";
|
|
201
|
+
canvasCtx.fillRect(Math.ceil((position - minimumPosition) /
|
|
202
|
+
lengthCanvas * width) - 1,
|
|
203
|
+
5,
|
|
204
|
+
5,
|
|
205
|
+
height);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Scale given bufferedData in terms of percentage between the minimum and
|
|
211
|
+
* maximum position. Filter out ranges which are not part of it.
|
|
212
|
+
* @param {Array.<Object>} bufferedData
|
|
213
|
+
* @param {number} minimumPosition
|
|
214
|
+
* @param {number} maximumPosition
|
|
215
|
+
* @returns {Array.<Object>}
|
|
216
|
+
*/
|
|
217
|
+
function scaleSegments(
|
|
218
|
+
bufferedData : IBufferedChunk[],
|
|
219
|
+
minimumPosition : number,
|
|
220
|
+
maximumPosition : number
|
|
221
|
+
) : IScaledChunk[] {
|
|
222
|
+
const scaledSegments = [];
|
|
223
|
+
const wholeDuration = maximumPosition - minimumPosition;
|
|
224
|
+
for (let i = 0; i < bufferedData.length; i++) {
|
|
225
|
+
const info = bufferedData[i];
|
|
226
|
+
const start = info.bufferedStart === undefined ?
|
|
227
|
+
info.start :
|
|
228
|
+
info.bufferedStart;
|
|
229
|
+
const end = info.bufferedEnd === undefined ?
|
|
230
|
+
info.end :
|
|
231
|
+
info.bufferedEnd;
|
|
232
|
+
if (end > minimumPosition && start < maximumPosition) {
|
|
233
|
+
const startPoint = Math.max(start - minimumPosition, 0);
|
|
234
|
+
const endPoint = Math.min(end - minimumPosition, maximumPosition);
|
|
235
|
+
const scaledStart = startPoint / wholeDuration;
|
|
236
|
+
const scaledEnd = endPoint / wholeDuration;
|
|
237
|
+
scaledSegments.push({ scaledStart, scaledEnd, info });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return scaledSegments;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
interface IScaledChunk {
|
|
244
|
+
scaledStart: number;
|
|
245
|
+
scaledEnd: number;
|
|
246
|
+
info: IBufferedChunk;
|
|
247
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maximum history of the buffer size that will be displayed, in milliseconds.
|
|
3
|
+
* For example, a value of `3000` indicates that we will just show at most the
|
|
4
|
+
* buffer size evolution during the last 3 seconds.
|
|
5
|
+
*/
|
|
6
|
+
const TIME_SAMPLES_MS = 30000;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* At minimum, that value will be taken in the chart as a maximum buffer size,
|
|
10
|
+
* in seconds.
|
|
11
|
+
* If samples go higher than this size, the chart will adapt automatically to
|
|
12
|
+
* a higher scale.
|
|
13
|
+
* However if values go below that value, the chart won't scale down more than
|
|
14
|
+
* this.
|
|
15
|
+
*/
|
|
16
|
+
const MINIMUM_MAX_BUFFER_SIZE = 20;
|
|
17
|
+
|
|
18
|
+
export default class BufferSizeGraph {
|
|
19
|
+
private _history : IHistoryItem[];
|
|
20
|
+
|
|
21
|
+
/** Canvas that will contain the buffer size graph itself. */
|
|
22
|
+
private readonly _canvasElt : HTMLCanvasElement;
|
|
23
|
+
|
|
24
|
+
private readonly _canvasCtxt : CanvasRenderingContext2D | null;
|
|
25
|
+
|
|
26
|
+
constructor(canvasElt : HTMLCanvasElement) {
|
|
27
|
+
this._canvasElt = canvasElt;
|
|
28
|
+
this._canvasCtxt = this._canvasElt.getContext("2d");
|
|
29
|
+
this._history = [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public pushBufferSize(bufferSize : number) : void {
|
|
33
|
+
const now = performance.now();
|
|
34
|
+
this._history.push({ timestamp: now, bufferSize });
|
|
35
|
+
if (this._history.length > 0) {
|
|
36
|
+
const minimumTime = now - TIME_SAMPLES_MS;
|
|
37
|
+
let i;
|
|
38
|
+
for (i = this._history.length - 1; i >= 1; i--) {
|
|
39
|
+
if (this._history[i].timestamp <= minimumTime) {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
this._history = this._history.slice(i);
|
|
44
|
+
} else {
|
|
45
|
+
this._history = [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public clear() {
|
|
50
|
+
if (this._canvasCtxt !== null) {
|
|
51
|
+
this._canvasCtxt.clearRect(0, 0, this._canvasElt.width, this._canvasElt.height);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public reRender(width : number, height : number) : void {
|
|
56
|
+
this._canvasElt.style.width = `${width}px`;
|
|
57
|
+
this._canvasElt.style.height = `${height}px`;
|
|
58
|
+
this._canvasElt.width = width;
|
|
59
|
+
this._canvasElt.height = height;
|
|
60
|
+
this.clear();
|
|
61
|
+
const history = this._history;
|
|
62
|
+
const canvasCtx = this._canvasCtxt;
|
|
63
|
+
|
|
64
|
+
if (history.length === 0) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const currentMaxSize = getNewMaxBufferSize();
|
|
69
|
+
const minDate = history[0].timestamp;
|
|
70
|
+
|
|
71
|
+
const gridHeight = height / currentMaxSize;
|
|
72
|
+
const gridWidth = width / TIME_SAMPLES_MS;
|
|
73
|
+
|
|
74
|
+
drawData();
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get more appropriate maximum buffer size to put on top of the graph
|
|
78
|
+
* according to current history.
|
|
79
|
+
*/
|
|
80
|
+
function getNewMaxBufferSize() {
|
|
81
|
+
const maxPoint = Math.max(...history.map(d => d.bufferSize));
|
|
82
|
+
return Math.max(maxPoint + 5, MINIMUM_MAX_BUFFER_SIZE);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Draw all data contained in `history` in the canvas given.
|
|
87
|
+
*/
|
|
88
|
+
function drawData() {
|
|
89
|
+
if (canvasCtx === null) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
canvasCtx.beginPath();
|
|
93
|
+
canvasCtx.fillStyle = "rgb(200, 100, 200)";
|
|
94
|
+
for (let i = 1; i < history.length; i++) {
|
|
95
|
+
const diff = dateToX(history[i].timestamp) -
|
|
96
|
+
dateToX(history[i - 1].timestamp);
|
|
97
|
+
const y = height - bufferValueToHeight(history[i].bufferSize);
|
|
98
|
+
canvasCtx.fillRect(
|
|
99
|
+
dateToX(history[i - 1].timestamp),
|
|
100
|
+
y,
|
|
101
|
+
diff,
|
|
102
|
+
height);
|
|
103
|
+
}
|
|
104
|
+
canvasCtx.stroke();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Convert a value of a given data point, to a u coordinate in the canvas.
|
|
109
|
+
* @param {number} bufferVal - Value to convert
|
|
110
|
+
* @returns {number} - y coordinate
|
|
111
|
+
*/
|
|
112
|
+
function bufferValueToHeight(bufferVal : number) : number {
|
|
113
|
+
return height - (currentMaxSize - bufferVal) * gridHeight;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Convert a date of a given data point, to a x coordinate in the canvas.
|
|
118
|
+
* @param {number} date - Date to convert, in milliseconds
|
|
119
|
+
* @returns {number} - x coordinate
|
|
120
|
+
*/
|
|
121
|
+
function dateToX(date : number) : number {
|
|
122
|
+
return (date - minDate) * gridWidth;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface IHistoryItem {
|
|
128
|
+
timestamp : number;
|
|
129
|
+
bufferSize : number;
|
|
130
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { CancellationSignal } from "../../../../utils/task_canceller";
|
|
2
|
+
import RxPlayer from "../../public_api";
|
|
3
|
+
import { DEFAULT_REFRESH_INTERVAL } from "../constants";
|
|
4
|
+
import {
|
|
5
|
+
createCompositeElement,
|
|
6
|
+
createElement,
|
|
7
|
+
createMetricTitle,
|
|
8
|
+
isExtendedMode,
|
|
9
|
+
} from "../utils";
|
|
10
|
+
|
|
11
|
+
export default function constructDebugGeneralInfo(
|
|
12
|
+
instance : RxPlayer,
|
|
13
|
+
parentElt : HTMLElement,
|
|
14
|
+
cancelSignal : CancellationSignal
|
|
15
|
+
) : HTMLElement {
|
|
16
|
+
const generalInfoElt = createElement("div");
|
|
17
|
+
const adaptationsElt = createElement("div");
|
|
18
|
+
const representationsElt = createElement("div");
|
|
19
|
+
updateGeneralInfo();
|
|
20
|
+
const generalInfoItv = setInterval(() => {
|
|
21
|
+
updateGeneralInfo();
|
|
22
|
+
}, DEFAULT_REFRESH_INTERVAL);
|
|
23
|
+
cancelSignal.register(() => {
|
|
24
|
+
clearInterval(generalInfoItv);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return createCompositeElement("div", [
|
|
28
|
+
generalInfoElt,
|
|
29
|
+
adaptationsElt,
|
|
30
|
+
representationsElt,
|
|
31
|
+
]);
|
|
32
|
+
function updateGeneralInfo() {
|
|
33
|
+
const videoElement = instance.getVideoElement();
|
|
34
|
+
if (videoElement === null) {
|
|
35
|
+
// disposed player. Clean-up everything
|
|
36
|
+
generalInfoElt.innerHTML = "";
|
|
37
|
+
adaptationsElt.innerHTML = "";
|
|
38
|
+
representationsElt.innerHTML = "";
|
|
39
|
+
clearInterval(generalInfoItv);
|
|
40
|
+
return;
|
|
41
|
+
} else {
|
|
42
|
+
const currentTime = instance.getPosition();
|
|
43
|
+
const bufferGap = instance.getCurrentBufferGap();
|
|
44
|
+
const bufferGapStr = bufferGap === Infinity ? "0" : bufferGap.toFixed(2);
|
|
45
|
+
const valuesLine1 : Array<[string, string]> = [
|
|
46
|
+
["ct", currentTime.toFixed(2)],
|
|
47
|
+
["bg", bufferGapStr],
|
|
48
|
+
["rs", String(videoElement.readyState)],
|
|
49
|
+
["pr", String(videoElement.playbackRate)],
|
|
50
|
+
["sp", String(instance.getPlaybackRate())],
|
|
51
|
+
["pa", String(videoElement.paused ? 1 : 0)],
|
|
52
|
+
["en", String(videoElement.ended ? 1 : 0)],
|
|
53
|
+
["li", String(instance.isLive() ? 1 : 0)],
|
|
54
|
+
["wba", String(instance.getWantedBufferAhead())],
|
|
55
|
+
["st", `"${instance.getPlayerState()}"`],
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
const valuesLine2 : Array<[string, string]> = [];
|
|
59
|
+
const ks = instance.getKeySystemConfiguration();
|
|
60
|
+
if (ks !== null) {
|
|
61
|
+
valuesLine2.push(["ks", ks.keySystem]);
|
|
62
|
+
}
|
|
63
|
+
const mbb = instance.getMaxBufferBehind();
|
|
64
|
+
if (mbb !== Infinity) {
|
|
65
|
+
valuesLine2.push(["mbb", String(mbb)]);
|
|
66
|
+
}
|
|
67
|
+
const mba = instance.getMaxBufferAhead();
|
|
68
|
+
if (mba !== Infinity) {
|
|
69
|
+
valuesLine2.push(["mba", String(mba)]);
|
|
70
|
+
}
|
|
71
|
+
const mbs = instance.getMaxVideoBufferSize();
|
|
72
|
+
if (mbs !== Infinity) {
|
|
73
|
+
valuesLine2.push(["mbs", String(mbs)]);
|
|
74
|
+
}
|
|
75
|
+
const minPos = instance.getMinimumPosition();
|
|
76
|
+
if (minPos !== null) {
|
|
77
|
+
valuesLine1.push(["mip", minPos.toFixed(2)]);
|
|
78
|
+
valuesLine2.push(["dmi", (currentTime - minPos).toFixed(2)]);
|
|
79
|
+
}
|
|
80
|
+
const maxPos = instance.getMaximumPosition();
|
|
81
|
+
if (maxPos !== null) {
|
|
82
|
+
valuesLine1.push(["map", maxPos.toFixed(2)]);
|
|
83
|
+
valuesLine2.push(["dma", (maxPos - currentTime).toFixed(2)]);
|
|
84
|
+
}
|
|
85
|
+
const valuesLine3 : Array<[string, string]> = [];
|
|
86
|
+
const error = instance.getError();
|
|
87
|
+
if (error !== null) {
|
|
88
|
+
valuesLine3.push(["er", `"${String(error)}"`]);
|
|
89
|
+
}
|
|
90
|
+
generalInfoElt.innerHTML = "";
|
|
91
|
+
for (const valueSet of [valuesLine1, valuesLine2, valuesLine3]) {
|
|
92
|
+
if (valueSet.length > 0) {
|
|
93
|
+
const lineInfoElt = createElement("div");
|
|
94
|
+
for (const value of valueSet) {
|
|
95
|
+
lineInfoElt.appendChild(createMetricTitle(value[0]));
|
|
96
|
+
lineInfoElt.appendChild(createElement("span", {
|
|
97
|
+
textContent: value[1] + " ",
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
generalInfoElt.appendChild(lineInfoElt);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (isExtendedMode(parentElt)) {
|
|
104
|
+
const url = instance.getContentUrls()?.[0];
|
|
105
|
+
if (url !== undefined) {
|
|
106
|
+
const reducedUrl = url.length > 100 ?
|
|
107
|
+
url.substring(0, 99) + "…" :
|
|
108
|
+
url;
|
|
109
|
+
|
|
110
|
+
generalInfoElt.appendChild(createCompositeElement("div", [
|
|
111
|
+
createMetricTitle("url"),
|
|
112
|
+
createElement("span", {
|
|
113
|
+
textContent: reducedUrl,
|
|
114
|
+
}),
|
|
115
|
+
]));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (isExtendedMode(parentElt)) {
|
|
120
|
+
const videoId = instance.getAvailableVideoTracks().map(({ id, active }) =>
|
|
121
|
+
active ? `*${id}` : id);
|
|
122
|
+
const audioId = instance.getAvailableAudioTracks().map(({ id, active }) =>
|
|
123
|
+
active ? `*${id}` : id);
|
|
124
|
+
const textId = instance.getAvailableTextTracks().map(({ id, active }) =>
|
|
125
|
+
active ? `*${id}` : id);
|
|
126
|
+
adaptationsElt.innerHTML = "";
|
|
127
|
+
if (videoId.length > 0) {
|
|
128
|
+
let textContent = `${videoId.length}:${videoId.join(" ")} `;
|
|
129
|
+
if (textContent.length > 100) {
|
|
130
|
+
textContent = textContent.substring(0, 98) + "… ";
|
|
131
|
+
}
|
|
132
|
+
const videoAdaps = createCompositeElement("div", [
|
|
133
|
+
createMetricTitle("vt"),
|
|
134
|
+
createElement("span", { textContent }),
|
|
135
|
+
]);
|
|
136
|
+
adaptationsElt.appendChild(videoAdaps);
|
|
137
|
+
}
|
|
138
|
+
if (audioId.length > 0) {
|
|
139
|
+
let textContent = `${audioId.length}:${audioId.join(" ")} `;
|
|
140
|
+
if (textContent.length > 100) {
|
|
141
|
+
textContent = textContent.substring(0, 98) + "… ";
|
|
142
|
+
}
|
|
143
|
+
const audioAdaps = createCompositeElement("div", [
|
|
144
|
+
createMetricTitle("at"),
|
|
145
|
+
createElement("span", { textContent }),
|
|
146
|
+
]);
|
|
147
|
+
adaptationsElt.appendChild(audioAdaps);
|
|
148
|
+
}
|
|
149
|
+
if (textId.length > 0) {
|
|
150
|
+
let textContent = `${textId.length}:${textId.join(" ")} `;
|
|
151
|
+
if (textContent.length > 100) {
|
|
152
|
+
textContent = textContent.substring(0, 98) + "… ";
|
|
153
|
+
}
|
|
154
|
+
const textAdaps = createCompositeElement("div", [
|
|
155
|
+
createMetricTitle("tt"),
|
|
156
|
+
createElement("span", { textContent }),
|
|
157
|
+
]);
|
|
158
|
+
adaptationsElt.appendChild(textAdaps);
|
|
159
|
+
}
|
|
160
|
+
const videoBitrates = instance.getVideoTrack()?.representations.map(r => {
|
|
161
|
+
return r.bitrate;
|
|
162
|
+
}).filter(bitrate => bitrate !== undefined) ?? [];
|
|
163
|
+
const audioBitrates = instance.getAudioTrack()?.representations.map(r => {
|
|
164
|
+
return r.bitrate;
|
|
165
|
+
}).filter(bitrate => bitrate !== undefined) ?? [];
|
|
166
|
+
representationsElt.innerHTML = "";
|
|
167
|
+
if (videoBitrates.length > 0) {
|
|
168
|
+
representationsElt.appendChild(createMetricTitle("vb"));
|
|
169
|
+
representationsElt.appendChild(createElement("span", {
|
|
170
|
+
textContent: videoBitrates.join(" ") + " ",
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
if (audioBitrates.length > 0) {
|
|
174
|
+
representationsElt.appendChild(createMetricTitle("ab"));
|
|
175
|
+
representationsElt.appendChild(createElement("span", {
|
|
176
|
+
textContent: audioBitrates.join(" ") + " ",
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
adaptationsElt.innerHTML = "";
|
|
181
|
+
representationsElt.innerHTML = "";
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|