OverviewFilesCommitsIssuesDocsReleasesPeers

kodi-jacktook commits / 655d2c9

Set only the two ISA properties known to produce audio (1.15.8)
The ISA path set five things: inputstream, manifest_type, manifest_headers, stream_headers and mimetype. The .strm configuration that was confirmed by ear to have working audio on this exact stream set only the first two. Playback through Jacktook was silent while the .strm was not, so drop the extras and reproduce the known-good setup exactly. Why the removed ones are not needed anyway: * mimetype -- ISA already has the type from manifest_type. * manifest_headers / stream_headers -- measured against the live CDN, master, variant and segments all return 200/200/206 with no headers whatsoever, so there is nothing for them to buy on this source. Neither could be exonerated from the logs. Both a bisect on the codec-open line and one on the stall line came back inconclusive: audio opens once and stalls once during startup buffering in EVERY variant, including the audible one. The log cannot distinguish audible from silent here, so matching a configuration known to work beats another theory about why. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
655d2c9ade3552f98c84ae204e2ceb15279a36df
by plankatron <fleeky@gmail.com> · 2026-08-11T00:14:01.000Z

Changed files (3) +26 -48

plugin.video.jacktook/addon.xml +1 -1
……@@ -1,5 +1,5 @@
11<?xml version="1.0" encoding="utf-8"?>
2 <addon id="plugin.video.jacktook" name="Jacktook" version="1.15.7" provider-name="Sam-Max">
2 <addon id="plugin.video.jacktook" name="Jacktook" version="1.15.8" provider-name="Sam-Max">
33 <requires>
44 <import addon="xbmc.python" version="3.00.0"/>
55 <import addon="script.module.requests" version="2.25.1"/>
plugin.video.jacktook/lib/utils/player/utils.py +15 -14
……@@ -109,22 +109,23 @@ def set_adaptive_stream(list_item, data: Dict[str, Any]) -> Optional[str]:
109109 if not kind:
110110 return None
111111
112 # Exactly two properties, matching the .strm configuration that was
113 # confirmed by ear to have working audio on this content.
114 #
115 # Deliberately NOT set, because that .strm did not set them and the version
116 # that did was silent:
117 # * mimetype -- ISA already knows the type from manifest_type.
118 # * manifest_headers / stream_headers -- measured 2026-08-10, this CDN
119 # serves master, variant AND segments with no headers at all (200/200/
120 # 206), so there is nothing for them to buy here.
121 # Neither could be exonerated from the logs: audio opens and stalls once on
122 # startup in every variant, so the log cannot distinguish audible from
123 # silent. Rather than keep guessing, reproduce the known-good setup exactly.
124 # If a future source genuinely needs headers, add them back behind that
125 # source rather than for everything.
112126 list_item.setProperty("inputstream", "inputstream.adaptive")
113127 list_item.setProperty("inputstream.adaptive.manifest_type", kind)
114
115 headers = data.get("proxyHeaders") or {}
116 encoded = "&".join(
117 f"{key}={quote(str(value), safe='')}"
118 for key, value in headers.items()
119 if key and value
120 )
121 if encoded:
122 list_item.setProperty("inputstream.adaptive.manifest_headers", encoded)
123 list_item.setProperty("inputstream.adaptive.stream_headers", encoded)
124
125 list_item.setMimeType(ADAPTIVE_MIMETYPES[kind])
126 list_item.setContentLookup(False)
127 kodilog(f"[PLAYER] inputstream.adaptive engaged ({kind}), headers={bool(encoded)}")
128 kodilog(f"[PLAYER] inputstream.adaptive engaged ({kind}), minimal props")
128129 return url.split("|", 1)[0]
129130
130131
plugin.video.jacktook/tests/unit/test_adaptive_stream.py +10 -33
……@@ -57,39 +57,6 @@ def test_strips_the_header_suffix_from_the_played_url():
5757 assert "|" not in url
5858
5959
60def test_headers_move_to_isa_properties():
61 item = MagicMock()
62 set_adaptive_stream(
63 item,
64 {
65 "adaptive": True,
66 "url": "http://h/a.m3u8",
67 "proxyHeaders": {"Referer": "https://vidcore.net/", "User-Agent": "UA/1.0"},
68 },
69 )
70 props = dict(c.args for c in item.setProperty.call_args_list)
71 for key in ("inputstream.adaptive.manifest_headers", "inputstream.adaptive.stream_headers"):
72 assert "Referer=https%3A%2F%2Fvidcore.net%2F" in props[key]
73 assert "User-Agent=UA%2F1.0" in props[key]
74
75
76def test_no_header_properties_when_there_are_none():
77 item = MagicMock()
78 set_adaptive_stream(item, {"adaptive": True, "url": "http://h/a.m3u8"})
79 props = dict(c.args for c in item.setProperty.call_args_list)
80 assert "inputstream.adaptive.manifest_headers" not in props
81
82
83def test_mimetype_is_set_per_manifest_kind():
84 for url, mime in (
85 ("http://h/a.m3u8", "application/vnd.apple.mpegurl"),
86 ("http://h/a.mpd", "application/dash+xml"),
87 ):
88 item = MagicMock()
89 set_adaptive_stream(item, {"adaptive": True, "url": url})
90 item.setMimeType.assert_called_once_with(mime)
91
92
9360def test_isa_is_off_unless_a_source_opts_in():
9461 """Regression, 2026-08-10: engaging ISA for every .m3u8 captured the
9562 single-variant rows too, and ISA stalls the audio on muxed HLS -- the aac
……@@ -128,3 +95,13 @@ def test_adaptive_items_are_opened_once():
12895 assert 'double_open = not is_plugin and not getattr(self, "_adaptive", False)' in src
12996 assert 'if double_open:' in src
13097 assert 'self._adaptive = bool(adaptive_url)' in src
98
99def test_only_the_two_known_good_properties_are_set():
100 """Audio was silent with mimetype and header properties set, and audible
101 without them on the same stream. Keep the property set minimal."""
102 item = MagicMock()
103 set_adaptive_stream(item, {"adaptive": True, "url": "http://h/a.m3u8",
104 "proxyHeaders": {"Referer": "https://vidcore.net/"}})
105 props = dict(c.args for c in item.setProperty.call_args_list)
106 assert set(props) == {"inputstream", "inputstream.adaptive.manifest_type"}
107 item.setMimeType.assert_not_called()