Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
664cfa6
docs(cmcd): Add design spec for CMCD CML refactor
littlespex Apr 28, 2026
26db780
docs(cmcd): Revise design spec with gap-fixes from hls.js/dash.js audit
littlespex Apr 28, 2026
887c988
docs(cmcd): add implementation plan
littlespex Apr 28, 2026
7970253
docs(cmcd): add Phase 0 CML version pin + API verification report
littlespex Apr 28, 2026
33c7c78
docs(cmcd): fix doc cross-references in Phase 0 verification report
littlespex Apr 28, 2026
be97afe
docs(cmcd): restructure Phase 0 doc-update checklist into plan vs spe…
littlespex Apr 28, 2026
6a851a2
docs(cmcd): apply Phase 0 verification findings to spec and plan
littlespex Apr 28, 2026
a8d8551
chore(third_party): add cml-cmcd vendoring skeleton
littlespex Apr 28, 2026
0027abb
chore(cmcd): port cml-cmcd type definitions as closure typedefs
littlespex Apr 28, 2026
ae92000
chore(cmcd): port cml-cmcd enums to closure
littlespex Apr 28, 2026
c4d84a2
chore(cmcd): port cml-cmcd constants to closure
littlespex Apr 28, 2026
1e539e7
chore(cmcd): port cml-cmcd uuid shim
littlespex Apr 28, 2026
e6cb256
chore(cmcd): wire phase 1A port into build, add doc consistency
littlespex Apr 28, 2026
1b51edf
chore(cmcd): vendor cml-utils + cml-sfv shims for encoder port
littlespex Apr 28, 2026
7a27aaa
chore(cmcd): port CMCD_FORMATTER_MAP (deferred from sub-phase A)
littlespex Apr 28, 2026
3d6d5ae
chore(cmcd): port cml-cmcd encoders to closure
littlespex Apr 28, 2026
d9aa2f9
chore(cmcd): port cml-cmcd version-resolution helpers
littlespex Apr 28, 2026
9bcf661
fix(cmcd): restore typedef requireType in cmcd.js/event/response, pol…
littlespex Apr 28, 2026
988712e
chore(cmcd): port CmcdReporter-only typedefs (deferred from sub-phase A)
littlespex Apr 28, 2026
3de73b2
chore(cmcd): port cml-cmcd CmcdReporter to closure
littlespex Apr 28, 2026
d682bb1
fix(cmcd): tighten transmissionMode typedef, unify ?? fallbacks in re…
littlespex Apr 28, 2026
0f69e7f
docs(cmcd): add Phase 1 sub-phase A-C completion status to plan
littlespex Apr 28, 2026
d8d614c
refactor(cmcd): delegate encoding to vendored cml-cmcd
littlespex Apr 28, 2026
adfdfab
fix(cmcd): drop non-spec 'ld'/'lh' StreamingFormat values
littlespex Apr 28, 2026
4aa5ff7
docs(cmcd): mark Phase 1 sub-phase D complete in plan
littlespex Apr 28, 2026
27cd169
fix(cmcd): thread version/reportingMode + prepare-once for header shards
littlespex Apr 28, 2026
b94f7eb
test(cmcd): update assertions for CML wire-format alignments
littlespex Apr 28, 2026
0e38831
docs(cmcd): mark Phase 1 sub-phase E complete in plan
littlespex Apr 28, 2026
d663f6c
docs(cmcd): mark Phase 1 sub-phase F complete; add all-phases PR draft
littlespex Apr 28, 2026
67443aa
refactor(cmcd): adopt CML constants/enums; delete shaka duplicates
littlespex Apr 28, 2026
f0b99a8
docs(cmcd): mark Phase 2 complete in plan; rename PR draft to cumulative
littlespex Apr 28, 2026
1352a01
docs(cmcd): expand Phase 3 prep with concrete session-context handoff
littlespex Apr 28, 2026
965ba69
refactor(cmcd): rewrite shaka.util.CmcdManager as thin adapter around…
littlespex Apr 29, 2026
43cc7f3
fix(cmcd): preserve video_ across reset() so configure() can rebuild …
littlespex Apr 29, 2026
fb54b54
docs(cmcd): mark Phase 3 complete; cumulative PR draft now spans all …
littlespex Apr 29, 2026
71a1e96
chore: remove plan files
littlespex Apr 29, 2026
67986bf
fix(cmcd): repair 410 interval leak, requestTimestampMap_ growth, mis…
Copilot Apr 29, 2026
dda7c17
fix(cmcd): use strict equality for null checks on lastPlayerState_
Copilot Apr 29, 2026
332f9e5
docs(cmcd): correct third_party/SUMMARY.txt to match what's vendored
littlespex Apr 29, 2026
64767e6
Merge branch 'main' into feat/cmcd-cml-refactor
littlespex May 5, 2026
1fab16c
chore: remove unused default request function
littlespex May 5, 2026
7ebdee3
Merge branch 'main' into feat/cmcd-cml-refactor
littlespex May 13, 2026
1b0c578
fix: incorrect request type
littlespex May 13, 2026
ce1a855
chore(cmcd): bump cml-cmcd to v2.3.2 + fix three regressions
littlespex May 13, 2026
0627845
Merge branch 'main' into feat/cmcd-cml-refactor
littlespex May 26, 2026
1b41275
refactor(UI): Unify localization and availability updates in Element …
avelad May 27, 2026
f367ee5
feat(Queue): Add M3U playlist loading support (#10115)
avelad May 27, 2026
a479eae
fix: Emit ratechange event when playbackRate stays at 0 (#10130)
avelad May 27, 2026
ad8b674
refactor: Improve code of NativeTextDisplayer (#10106)
avelad May 27, 2026
921206d
feat: transmux in a worker (#9914)
vanyaxk May 27, 2026
1841e3a
fix(demo): Re-enable lazy localization (#10137)
joeyparrish May 28, 2026
66ba6e3
fix(UI): Use consistent font throughout UI (#10138)
joeyparrish May 28, 2026
d295a0a
fix(UI): Sync Document PiP placeholder with video poster changes (#10…
avelad May 28, 2026
61e64a9
build(deps): bump tmp from 0.2.4 to 0.2.7 (#10139)
dependabot[bot] May 28, 2026
f2de748
feat(UI): Update playback rate menu with slider and preset pills (#10…
avelad May 28, 2026
c433bcb
feat(UI): Support Document PiP for audio-only playback (#10136)
avelad May 28, 2026
ad4b624
fix(Cast): Proxy missing ad events through CastProxy (#10142)
avelad May 28, 2026
ee9436b
fix(UI): Update play button state on shaka.ads.Utils.AD_PLAYING (#10143)
avelad May 28, 2026
d61c85e
chore(Demo): Add back Tengwar font (#10147)
joeyparrish May 28, 2026
7108d22
feat(UI): Redesign Document PiP placeholder with blurred backdrop, pu…
avelad May 28, 2026
98a197d
chore: Update Sindarin (sjn) locale (#10148)
shaka-translation-bot May 28, 2026
686d550
feat(UI): Modernize the statistics panel (#10144)
avelad May 28, 2026
52e7da0
build(UI): Migrate CSS pipeline to PostCSS for prefixing and optimiza…
avelad May 28, 2026
2e13ea2
fix(HLS): Fix LL-HLS stall on live playlist updates after #9998 (#10154)
felri May 29, 2026
814aaa7
refactor(UI): Avoid repeated localization.resolve calls (#10155)
avelad May 29, 2026
8ba0419
feat(cmcd): bump cml-cmcd to v2.4.0 + add integration test (#17)
littlespex May 29, 2026
cbdaeed
Merge branch 'main' into feat/cmcd-cml-refactor
littlespex May 29, 2026
7aefbd6
chore: lint fix
littlespex May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions build/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,16 @@ def main(args):
for mode in modes:
tasks = []

worker_args = [
'--worker', '--name', 'transmuxer-worker',
'+@transmuxer-worker', '--langout', 'ECMASCRIPT5', '--mode', mode,
]
if parsed_args.force:
worker_args += ['--force']
tasks.append((
[sys.executable, os.path.join(base, 'build', 'build.py')] + worker_args,
os.environ.copy()))

for lang_out, suffix in language_variants:
for build_args in builds:
args = list(build_args)
Expand All @@ -242,6 +252,7 @@ def main(args):
# Add language and mode flags.
args += ['--langout', lang_out]
args += ['--mode', mode]
args += ['--skip-worker']

# Prepare environment and command for a separate process.
env = os.environ.copy()
Expand Down
81 changes: 78 additions & 3 deletions build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ def has_cast(self):
return True
return False

def has_transmuxer_proxy(self):
"""Returns True if the transmuxer proxy is in the build."""
for path in self.include:
if path.endswith('transmuxer_proxy.js'):
return True
return False

def generate_localizations(self, locales, force):
localizations = compiler.GenerateLocalizations(locales)
localizations.generate(force)
Expand Down Expand Up @@ -265,7 +272,56 @@ def parse_build(self, lines, root):

return True

def build_library(self, name, langout, locales, force, is_debug, skip_ts):
def build_worker_bundle(self, langout, force, is_debug):
"""Compiles the transmuxer worker bundle.

Returns True on success; False on failure.
"""
worker_build = Build()
if not worker_build.parse_build(['+@transmuxer-worker'], os.getcwd()):
return False
worker_build.add_closure()
if not worker_build.add_core():
return False

build_name = 'shaka-player.transmuxer-worker'
if is_debug:
build_name += '.debug'
closure = compiler.ClosureCompiler(worker_build.include, build_name)
closure.add_wrapper = False
closure.add_source_map = False

closure_opts = common_closure_opts + common_closure_defines
closure_opts += ['--language_out', langout]
if is_debug:
closure_opts += debug_closure_opts + debug_closure_defines
else:
closure_opts += release_closure_opts + release_closure_defines

closure_opts += [
'--dependency_mode=PRUNE',
'--entry_point=goog:shaka.transmuxer.TransmuxerWorker',
# Each transmuxer plugin registers itself at load time (side effect),
# so we must list them as entry points too.
'--entry_point=goog:shaka.transmuxer.AacTransmuxer',
'--entry_point=goog:shaka.transmuxer.Ac3Transmuxer',
'--entry_point=goog:shaka.transmuxer.Ec3Transmuxer',
'--entry_point=goog:shaka.transmuxer.Mp3Transmuxer',
'--entry_point=goog:shaka.transmuxer.MpegTsTransmuxer',
'--entry_point=goog:shaka.transmuxer.TsTransmuxer',
]

# Suppress type errors caused by dependency pruning; the main build
# already validates all types.
closure_opts += [
'--jscomp_off=checkTypes',
'--jscomp_off=unknownDefines',
]

return closure.compile(closure_opts, force)

def build_library(self, name, langout, locales, force, is_debug, skip_ts,
build_worker):
"""Builds Shaka Player using the files in |self.include|.

Args:
Expand All @@ -275,6 +331,7 @@ def build_library(self, name, langout, locales, force, is_debug, skip_ts):
force: True to rebuild, False to ignore if no changes are detected.
is_debug: True to compile for debugging, false for release.
skip_ts: True to skip generation of TypeScript definitions.
build_worker: True to build the standalone transmuxer worker if needed.

Returns:
True on success; False on failure.
Expand All @@ -289,6 +346,11 @@ def build_library(self, name, langout, locales, force, is_debug, skip_ts):
if not self.has_cast():
self.include.add(os.path.abspath('conditional/dummy_cast_proxy.js'))

if build_worker and self.has_transmuxer_proxy():
logging.info('Compiling transmuxer worker bundle...')
if not self.build_worker_bundle(langout, force, is_debug):
return False

if is_debug:
name += '.debug'

Expand Down Expand Up @@ -385,6 +447,16 @@ def main(args):
help='Skips generation of TypeScript definition files (.d.ts).',
action='store_true')

parser.add_argument(
'--worker',
help='Build only the standalone transmuxer worker script.',
action='store_true')

parser.add_argument(
'--skip-worker',
help='Do not build the standalone transmuxer worker alongside the library.',
action='store_true')

parsed_args, commands = parser.parse_known_args(args)

# Make the dist/ folder, ignore errors.
Expand Down Expand Up @@ -501,8 +573,11 @@ def locked_file_rw(path, create=False):
is_debug = parsed_args.mode == 'debug'
skip_ts = parsed_args.skip_ts

if not custom_build.build_library(name, langout, locales, force, is_debug,
skip_ts):
if parsed_args.worker:
if not custom_build.build_worker_bundle(langout, force, is_debug):
return 1
elif not custom_build.build_library(name, langout, locales, force, is_debug,
skip_ts, not parsed_args.skip_worker):
return 1

# Persist (merge) the updated state under lock so we don't clobber parallel updates.
Expand Down
10 changes: 7 additions & 3 deletions build/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"""This is used to validate that the library is correct.

This checks:
* All files in lib/ appear when compiling +@complete
* All files in lib/ appear in +@complete or another standalone build type
* Runs a compiler pass over the test code to check for type errors
* Run the linter to check for style violations.
"""
Expand Down Expand Up @@ -48,7 +48,11 @@ def complete_build_files():
# Normally we don't need to include @core, but because we look at the build
# object directly, we need to include it here. When using main(), it will
# call addCore which will ensure core is included.
if not complete.parse_build(['+@complete', '+@core'], os.getcwd()):
#
# Standalone build types are included here so their entry points are covered
# by the "all files are in a build" invariant without bloating +@complete.
if not complete.parse_build(
['+@complete', '+@core', '+@transmuxer-worker'], os.getcwd()):
logging.error('Error parsing complete build')
return False
return complete.include
Expand Down Expand Up @@ -120,7 +124,7 @@ def check_html_lint(args):

@_Check('complete')
def check_complete(_):
"""Checks whether the 'complete' build references every file.
"""Checks whether the build type definitions reference every file.

This is used by the build script to ensure that every file is included in at
least one build type.
Expand Down
22 changes: 19 additions & 3 deletions build/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def __init__(self, main_source_file, all_source_files, output):

def compile(self, force=False):
"""Compiles the main less file in |self.main_source_file| into the
|self.output| css file.
|self.output| css file and applies PostCSS Autoprefixer.

Args:
force: Generate the output even if the inputs have not changed.
Expand All @@ -342,8 +342,6 @@ def compile(self, force=False):

lessc = shakaBuildHelpers.get_node_binary('less', 'lessc')
less_options = [
# Enable the "clean-CSS" plugin to minify the output and strip out comments.
'--clean-css',
# Output a source map of the original CSS/less files.
'--source-map=' + self.output + '.map',
]
Expand All @@ -354,6 +352,24 @@ def compile(self, force=False):
logging.error('CSS compilation failed')
return False

# We look for the PostCSS binary within node_modules/postcss-cli
postcss = shakaBuildHelpers.get_node_binary('postcss-cli', 'postcss')
postcss_options = [
self.output,
'-o', self.output,
'--use', 'autoprefixer',
'--use', 'cssnano',
'--map',
]

# We define the specific browsers using the environment variable. These are
# the minimum browsers that the UI supports.
os.environ['BROWSERSLIST'] = 'chrome 38, safari 8, firefox 42'

if shakaBuildHelpers.execute_get_code(postcss + postcss_options) != 0:
logging.error('PostCSS / Autoprefixer processing failed')
return False

# We need to prepend the license header to the compiled CSS.
with open(_get_source_path('build/license-header'), 'rb') as f:
license_header = f.read()
Expand Down
3 changes: 3 additions & 0 deletions build/conformance.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ requirement: {
whitelist_regexp: "demo/"
whitelist_regexp: "test/"
whitelist_regexp: "lib/util/timer.js"
whitelist_regexp: "third_party/cml-cmcd/cmcd_reporter.js"
}
requirement: {
type: BANNED_NAME
Expand All @@ -248,6 +249,7 @@ requirement: {
whitelist_regexp: "demo/"
whitelist_regexp: "test/"
whitelist_regexp: "lib/util/timer.js"
whitelist_regexp: "third_party/cml-cmcd/cmcd_reporter.js"
}

# Disallow setTimeout.
Expand Down Expand Up @@ -313,6 +315,7 @@ requirement: {
"instead."
whitelist_regexp: "lib/net/http_fetch_plugin.js"
whitelist_regexp: "test/test/util/util.js"
whitelist_regexp: "third_party/cml-cmcd/cml_utils.js"
}

# Disallow the general use of AbortController, which is not available on all
Expand Down
76 changes: 76 additions & 0 deletions build/types/core
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
+../../lib/text/web_vtt_generator.js

+../../lib/transmuxer/transmuxer_engine.js
+../../lib/transmuxer/transmuxer_proxy.js
+../../lib/transmuxer/transmuxer_utils.js

+../../lib/util/abortable_operation.js
Expand Down Expand Up @@ -136,6 +137,81 @@
+../../third_party/closure-uri/uri.js
+../../third_party/closure-uri/utils.js

+../../third_party/cml-cmcd/append_cmcd_headers.js
+../../third_party/cml-cmcd/append_cmcd_query.js
+../../third_party/cml-cmcd/cmcd.js
+../../third_party/cml-cmcd/cmcd_custom_key.js
+../../third_party/cml-cmcd/cmcd_custom_value.js
+../../third_party/cml-cmcd/cmcd_data.js
+../../third_party/cml-cmcd/cmcd_default_time_interval.js
+../../third_party/cml-cmcd/cmcd_encode_options.js
+../../third_party/cml-cmcd/cmcd_event.js
+../../third_party/cml-cmcd/cmcd_event_keys.js
+../../third_party/cml-cmcd/cmcd_event_report_config.js
+../../third_party/cml-cmcd/cmcd_event_type.js
+../../third_party/cml-cmcd/cmcd_formatter.js
+../../third_party/cml-cmcd/cmcd_formatter_map.js
+../../third_party/cml-cmcd/cmcd_formatter_map_const.js
+../../third_party/cml-cmcd/cmcd_formatter_options.js
+../../third_party/cml-cmcd/cmcd_header_field.js
+../../third_party/cml-cmcd/cmcd_header_key.js
+../../third_party/cml-cmcd/cmcd_header_map.js
+../../third_party/cml-cmcd/cmcd_header_map_const.js
+../../third_party/cml-cmcd/cmcd_header_value.js
+../../third_party/cml-cmcd/cmcd_inner_list_keys.js
+../../third_party/cml-cmcd/cmcd_key.js
+../../third_party/cml-cmcd/cmcd_key_types.js
+../../third_party/cml-cmcd/cmcd_keys.js
+../../third_party/cml-cmcd/cmcd_mime_type.js
+../../third_party/cml-cmcd/cmcd_object_type.js
+../../third_party/cml-cmcd/cmcd_object_type_list.js
+../../third_party/cml-cmcd/cmcd_param.js
+../../third_party/cml-cmcd/cmcd_player_state.js
+../../third_party/cml-cmcd/cmcd_report_config.js
+../../third_party/cml-cmcd/cmcd_reporter.js
+../../third_party/cml-cmcd/cmcd_reporter_config.js
+../../third_party/cml-cmcd/cmcd_reporting_mode.js
+../../third_party/cml-cmcd/cmcd_request.js
+../../third_party/cml-cmcd/cmcd_request_key.js
+../../third_party/cml-cmcd/cmcd_request_keys.js
+../../third_party/cml-cmcd/cmcd_request_report.js
+../../third_party/cml-cmcd/cmcd_request_report_config.js
+../../third_party/cml-cmcd/cmcd_response.js
+../../third_party/cml-cmcd/cmcd_response_keys.js
+../../third_party/cml-cmcd/cmcd_state_event_fields.js
+../../third_party/cml-cmcd/cmcd_stream_type.js
+../../third_party/cml-cmcd/cmcd_streaming_format.js
+../../third_party/cml-cmcd/cmcd_string_length_limits.js
+../../third_party/cml-cmcd/cmcd_token_values.js
+../../third_party/cml-cmcd/cmcd_transmission_mode.js
+../../third_party/cml-cmcd/cmcd_v1.js
+../../third_party/cml-cmcd/cmcd_v1_const.js
+../../third_party/cml-cmcd/cmcd_v1_keys.js
+../../third_party/cml-cmcd/cmcd_v2_const.js
+../../third_party/cml-cmcd/cmcd_value.js
+../../third_party/cml-cmcd/cmcd_version.js
+../../third_party/cml-cmcd/cml_sfv.js
+../../third_party/cml-cmcd/cml_utils.js
+../../third_party/cml-cmcd/encode_cmcd.js
+../../third_party/cml-cmcd/encode_prepared_cmcd.js
+../../third_party/cml-cmcd/ensure_headers.js
+../../third_party/cml-cmcd/group_cmcd_headers.js
+../../third_party/cml-cmcd/is_cmcd_custom_key.js
+../../third_party/cml-cmcd/is_cmcd_event_key.js
+../../third_party/cml-cmcd/is_cmcd_request_key.js
+../../third_party/cml-cmcd/is_cmcd_response_received_key.js
+../../third_party/cml-cmcd/is_cmcd_v1_key.js
+../../third_party/cml-cmcd/is_token_field.js
+../../third_party/cml-cmcd/is_valid.js
+../../third_party/cml-cmcd/prepare_cmcd_data.js
+../../third_party/cml-cmcd/resolve_version.js
+../../third_party/cml-cmcd/to_cmcd_headers.js
+../../third_party/cml-cmcd/to_cmcd_query.js
+../../third_party/cml-cmcd/to_cmcd_url.js
+../../third_party/cml-cmcd/to_cmcd_value.js
+../../third_party/cml-cmcd/to_prepared_cmcd_headers.js
+../../third_party/cml-cmcd/up_convert_to_v2.js

+../../third_party/language-mapping-list/language-mapping-list.js

+@lcevc
10 changes: 10 additions & 0 deletions build/types/transmuxer-worker
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Transmuxer Worker bundle.
# This build type produces a standalone script to be loaded in a Web Worker.
# It includes all transmuxer plugins and the worker entry point.

+../../lib/device/apple_browser.js
+../../lib/device/default_browser.js
+@devices
+../../lib/transmuxer/loc_transmuxer.js
+../../lib/transmuxer/transmuxer_worker.js
+@transmuxer
Binary file added demo/TengwarTelcontar.woff2
Binary file not shown.
32 changes: 32 additions & 0 deletions demo/asset_card.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,38 @@ shakaDemo.AssetCard = class {
this.remakeButtonsFn_(this);
}

/**
* Adds a Play button for M3U playlist assets and shows the remaining
* base buttons ("Add to queue", "Start Preload") as disabled, since
* those operations are not applicable to playlist-type assets:
* - "Add to queue" would add the raw playlist URL, not its entries.
* - "Start Preload" has no meaning before the playlist is fetched.
*/
addBaseButtonsPlaylist() {
let disablePlay = false;

// Play loads the playlist via QueueManager.loadFromM3uPlaylist()
// and starts the first channel automatically.
this.addButton('Play', async () => {
if (disablePlay) {
return;
}
disablePlay = true;
await shakaDemoMain.loadAsset(this.asset_);
this.remakeButtons();
});

// Disabled: adding a raw playlist URL to an existing queue is not
// supported; the user should play the playlist directly instead.
const addToQueueButton = this.addButton('Add to queue', () => {});
addToQueueButton.setAttribute('disabled', '');

// Disabled: preloading a playlist URL is not meaningful before the
// playlist entries have been resolved.
const preloadButton = this.addButton('Start Preload', () => {});
preloadButton.setAttribute('disabled', '');
}

/** Adds basic buttons to the card ("play" and "preload"). */
addBaseButtons() {
let disableButtons = false;
Expand Down
Loading