Skip to content

Deno Integration - #165

Closed
firsttris wants to merge 9 commits into
masterfrom
deno-integration
Closed

Deno Integration#165
firsttris wants to merge 9 commits into
masterfrom
deno-integration

Conversation

@firsttris

@firsttris firsttris commented Jan 11, 2026

Copy link
Copy Markdown
Owner

@firsttris firsttris mentioned this pull request Jan 11, 2026
@gjedeer

gjedeer commented Jan 12, 2026

Copy link
Copy Markdown

@firsttris Thank you!

I can confirm it downloaded Deno nicely to ~/.kodi/userdata/addon_data/plugin.video.sendtokodi/deno/deno but it seems my IP is banned today so the end to end test has to wait

2026-01-12 11:17:30.866 T:711788    info <general>: plugin.video.sendtokodi: Configuring yt-dlp with Deno JavaScript runtime
2026-01-12 11:17:31.219 T:711788   error <general>: WARNING: Assuming --restrict-filenames since file system encoding cannot encode all characters. Set the LC_ALL environment variable to fix this.

2026-01-12 11:17:31.699 T:711088    info <general>: PulseAudio: Opened device Default in pcm mode with Buffersize 150 ms Periodsize 50 ms
2026-01-12 11:17:31.700 T:711088    info <general>: CActiveAESink::OpenSink - initialize sink
2026-01-12 11:17:33.307 T:711087   error <general>: ActiveAE::InitSink - failed to init
2026-01-12 11:17:34.758 T:711788   error <general>: WARNING: [youtube] 3rSfE43nEl4: Signature extraction failed: Some formats may be missing

2026-01-12 11:17:34.763 T:711788   error <general>: ERROR: [youtube] 3rSfE43nEl4: Sign in to confirm you’re not a bot. This helps protect our community. Learn more

2026-01-12 11:17:34.766 T:711788   error <general>: plugin.video.sendtokodi: Traceback (most recent call last):
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/YoutubeDL.py", line 1606, in wrapper
                                                       return func(self, *args, **kwargs)
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/YoutubeDL.py", line 1741, in __extract_info
                                                       ie_result = ie.extract(url)
                                                                   ^^^^^^^^^^^^^^^
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/extractor/common.py", line 734, in extract
                                                       ie_result = self._real_extract(url)
                                                                   ^^^^^^^^^^^^^^^^^^^^^^^
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/extractor/youtube.py", line 4182, in _real_extract
                                                       self.raise_no_formats(reason, expected=True)
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/extractor/common.py", line 1251, in raise_no_formats
                                                       raise ExtractorError(msg, expected=expected, video_id=video_id)
                                                   yt_dlp.utils.ExtractorError: [youtube] 3rSfE43nEl4: Sign in to confirm you’re not a bot. This helps protect our community. Learn more

                                                   During handling of the above exception, another exception occurred:

                                                   Traceback (most recent call last):
                                                     File "/home/gdr/.kodi/addons/plugin.video.sendtokodi/service.py", line 386, in <module>
                                                       result = ydl.extract_info(url, download=False)
                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/YoutubeDL.py", line 1595, in extract_info
                                                       return self.__extract_info(url, self.get_info_extractor(key), download, extra_info, process)
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/YoutubeDL.py", line 1624, in wrapper
                                                       self.report_error(str(e), e.format_traceback())
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/YoutubeDL.py", line 1073, in report_error
                                                       self.trouble(f'{self._format_err("ERROR:", self.Styles.ERROR)} {message}', *args, **kwargs)
                                                     File "/usr/lib/python3/dist-packages/yt_dlp/YoutubeDL.py", line 1012, in trouble
                                                       raise DownloadError(message, exc_info)
                                                   yt_dlp.utils.DownloadError: ERROR: [youtube] 3rSfE43nEl4: Sign in to confirm you’re not a bot. This helps protect our community. Learn more

2026-01-12 11:17:34.932 T:711030   error <general>: Playlist Player: skipping unplayable item: 0, path [plugin://plugin.video.sendtokodi/?https://www.youtube.com/watch?v=3rSfE43nEl4]
2026-01-12 11:17:35.807 T:711087   error <general>: ActiveAE::FlushEngine - failed to flush
2026-01-12 11:17:40.808 T:711087   error <general>: ActiveAE::InitSink - failed to init
2026-01-12 11:17:40.808 T:711087 warning <general>: CActiveAE::StateMachine - signal: 1 from port: OutputDataPort not handled for state: 2
2026-01-12 11:17:43.307 T:711087   error <general>: ActiveAE::FlushEngine - failed to flush

@firsttris

Copy link
Copy Markdown
Owner Author

did you try again?

@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

Something strange is happening, I get 403 on the stream URL (https://rr1---sn-ivgt1vou2pm-2v1s.googlevideo.com/videoplayback?expire=1768431922&ei=0sxnad....) with the deno PR, but I also get it when built from master. And cherry on top. yt-dlp works correctly on command line on the same machine (even without deno).

@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

But, hmm, I don't think deno is working.

2026-01-16 11:46:49.341 T:1091510   error <general>: WARNING: [youtube] J00GPOvD3LE: nsig extraction failed: You may experience throttling for some formats
                                                            n = TWRmubpEGEUhUFfVh ; player = https://www.youtube.com/s/player/c1c87fb0/player_es6.vflset/en_US/base.js

2026-01-16 11:46:49.458 T:1091510    info <general>: plugin.video.sendtokodi: Picked raw format 18 - 640x360 (360p, THROTTLED)

@firsttris

firsttris commented Jan 16, 2026

Copy link
Copy Markdown
Owner Author

yes i think the path for deno was not correct, also found some potential bug regarding 403. pushed another commit to this branch.

d230db8

@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

It played one video, failed with another, but I think Deno is in use. I added verbose: True to ydl options. See first line - deno is not listed as unavailable.

2026-01-16 14:51:53.131 T:1114354   error <general>: [debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno, node (unavailable), quickjs (unavailable)
2026-01-16 14:51:54.680 T:1114354   error <general>: [debug] [youtube] Forcing "main" player JS variant for player b95b0e7a
                                                           original url = /s/player/b95b0e7a/player_es6.vflset/en_US/base.js
2026-01-16 14:51:55.606 T:1114354   error <general>: [debug] [youtube] QFtCeGjKOxU: tv player response playability status: LOGIN_REQUIRED
2026-01-16 14:51:56.031 T:1114354   error <general>: [debug] [youtube] QFtCeGjKOxU: Detected experiment to bind GVS PO Token to video id.                                               

And the following log on a non-playing stream:

2026-01-16 14:56:44.667 T:1115604   error <general>: [debug] Sort order given by extractor: quality, res, fps, hdr:12, source, vcodec, channels, acodec, lang, proto
                                                   
2026-01-16 14:56:44.667 T:1115604   error <general>: [debug] Formats sorted by: hasvid, ie_pref, quality, res, fps, hdr:12(7), source, vcodec, channels, acodec, lang, proto, size, br, asr, vext, aext, hasaud, id
                                                   
2026-01-16 14:56:44.688 T:1115604   error <general>: [debug] Default format spec: bestvideo*+bestaudio/best
                                                   
2026-01-16 14:56:45.175 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 160 - 256x144 (144p, ANDR-S) to DASH manifest
2026-01-16 14:56:45.583 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 278 - 256x144 (144p, ANDR-S) to DASH manifest
2026-01-16 14:56:46.001 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 394 - 256x144 (144p, ANDR-S) to DASH manifest
2026-01-16 14:56:46.428 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 133 - 426x240 (240p, ANDR-S) to DASH manifest
2026-01-16 14:56:46.960 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 242 - 426x240 (240p, ANDR-S) to DASH manifest
2026-01-16 14:56:48.126 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 395 - 426x240 (240p, ANDR-S) to DASH manifest
2026-01-16 14:56:48.499 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 134 - 640x360 (360p, ANDR-S) to DASH manifest
2026-01-16 14:56:49.153 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 243 - 640x360 (360p, ANDR-S) to DASH manifest
2026-01-16 14:56:49.491 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 396 - 640x360 (360p, ANDR-S) to DASH manifest
2026-01-16 14:56:49.941 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 135 - 854x480 (480p, ANDR-S) to DASH manifest
2026-01-16 14:56:50.428 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 244 - 854x480 (480p, ANDR-S) to DASH manifest
2026-01-16 14:56:50.595 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 397 - 854x480 (480p, ANDR-S) to DASH manifest
2026-01-16 14:56:51.032 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 136 - 1280x720 (720p, ANDR-S) to DASH manifest
2026-01-16 14:56:51.377 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 247 - 1280x720 (720p, ANDR-S) to DASH manifest
2026-01-16 14:56:51.795 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 398 - 1280x720 (720p, ANDR-S) to DASH manifest
2026-01-16 14:56:52.175 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 137 - 1920x1080 (1080p, ANDR-S) to DASH manifest
2026-01-16 14:56:52.660 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 248 - 1920x1080 (1080p, ANDR-S) to DASH manifest
2026-01-16 14:56:53.001 T:1115604    info <general>: plugin.video.sendtokodi: Added video stream 399 - 1920x1080 (1080p, ANDR-S) to DASH manifest
2026-01-16 14:56:53.601 T:1115604    info <general>: plugin.video.sendtokodi: Added audio stream 251 - audio only (medium, ANDR-S) to DASH manifest
2026-01-16 14:56:53.603 T:1115604    info <general>: plugin.video.sendtokodi: Picked DASH with custom manifest
2026-01-16 14:56:53.603 T:1115604    info <general>: plugin.video.sendtokodi: creating list item for url http://127.0.0.1:43195/manifest.mpd
2026-01-16 14:56:53.608 T:1115604    info <general>: CPythonInvoker(2, /home/gdr/.kodi/addons/plugin.video.sendtokodi/service.py): waiting on thread 129887788590784
2026-01-16 14:56:53.624 T:1115660   error <general>: 127.0.0.1 - - [16/Jan/2026 14:56:53] "HEAD /manifest.mpd HTTP/1.1" 200 -
                                                   
2026-01-16 14:56:53.629 T:1114269    info <general>: VideoPlayer::OpenFile: plugin://plugin.video.sendtokodi/?https://www.youtube.com/watch?v=l4UgZBs7ZGo
2026-01-16 14:56:53.630 T:1115660   error <general>: 127.0.0.1 - - [16/Jan/2026 14:56:53] "HEAD /manifest.mpd HTTP/1.1" 200 -
                                                   
2026-01-16 14:56:53.631 T:1115661    info <general>: Creating InputStream
2026-01-16 14:56:53.637 T:1115661   error <general>: CVideoPlayer::OpenInputStream - error opening [plugin://plugin.video.sendtokodi/?https://www.youtube.com/watch?v=l4UgZBs7ZGo]

@firsttris

firsttris commented Jan 16, 2026

Copy link
Copy Markdown
Owner Author

thx for log, i found some more issues releated to headers, check again, if your issues are gone

631ac99

@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

Tried 2 videos, both failed unfortunately

2026-01-16 15:12:11.056 T:1117877    info <general>: * Adding remote mapping for device 'devinput-64'
2026-01-16 15:12:14.384 T:1117862 warning <general>: CGLContextEGL::SwapBuffers: last msc time greater than interval
2026-01-16 15:12:14.962 T:1117939    info <general>: plugin.video.sendtokodi: Configuring yt-dlp with Deno JavaScript runtime
2026-01-16 15:12:14.964 T:1117939   error <general>: [debug] Encodings: locale ANSI_X3.4-1968, fs ascii, pref ANSI_X3.4-1968, out missing (xbmcout) (No ANSI), error missing (replacement_stderr) (No ANSI), screen missing (xbmcout) (No ANSI)
                                                   
2026-01-16 15:12:14.964 T:1117939   error <general>: [debug] yt-dlp version stable@2025.12.08 from yt-dlp/yt-dlp [7a52ff29d] API
                                                   
2026-01-16 15:12:14.964 T:1117939   error <general>: [debug] params: {'extract_flat': 'in_playlist', 'verbose': True, 'js_runtimes': {'deno': {'path': '/home/gdr/.kodi/userdata/addon_data/plugin.video.sendtokodi/deno/deno'}}, 'remote_components': {'ejs:github'}, 'compat_opts': set(), 'http_headers': {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-us,en;q=0.5', 'Sec-Fetch-Mode': 'navigate'}}
                                                   
2026-01-16 15:12:15.191 T:1117939   error <general>: [debug] Lazy loading extractors is disabled
                                                   
2026-01-16 15:12:15.208 T:1117939   error <general>: [debug] Python 3.12.3 (CPython x86_64 64bit) - Linux-6.8.0-90-generic-x86_64-with-glibc2.39 (OpenSSL 3.0.13 30 Jan 2024, glibc 2.39)
                                                   
2026-01-16 15:12:15.342 T:1117939   error <general>: [debug] exe versions: ffmpeg 6.1.1 (setts), ffprobe 6.1.1
                                                   
2026-01-16 15:12:15.342 T:1117939   error <general>: [debug] Optional libraries: Cryptodome-3.20.0, brotli-1.1.0, certifi-2023.05.07, mutagen-1.46.0, requests-2.31.0 (unsupported), secretstorage-3.3.3, sqlite3-3.45.1, urllib3-2.2.3, websockets-10.4 (unsupported)
                                                   
2026-01-16 15:12:15.350 T:1117939   error <general>: [debug] JS runtimes: deno-2.6.4
                                                   
2026-01-16 15:12:15.350 T:1117939   error <general>: [debug] Proxy map: {}
                                                   
2026-01-16 15:12:15.351 T:1117939   error <general>: [debug] Request Handlers: urllib
                                                   
2026-01-16 15:12:15.352 T:1117939   error <general>: [debug] Plugin directories: none
                                                   
2026-01-16 15:12:15.399 T:1117939   error <general>: [debug] Loaded 1853 extractors
                                                   
2026-01-16 15:12:15.399 T:1117939   error <general>: WARNING: Assuming --restrict-filenames since file system encoding cannot encode all characters. Set the LC_ALL environment variable to fix this.
                                                   
2026-01-16 15:12:15.448 T:1117939   error <general>: [debug] Loaded 1853 extractors
                                                   
2026-01-16 15:12:15.757 T:1117939   error <general>: [debug] [youtube] [pot] PO Token Providers: none
                                                   
2026-01-16 15:12:15.757 T:1117939   error <general>: [debug] [youtube] [pot] PO Token Cache Providers: memory
                                                   
2026-01-16 15:12:15.757 T:1117939   error <general>: [debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
                                                   
2026-01-16 15:12:15.758 T:1117939   error <general>: [debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno, node (unavailable), quickjs (unavailable)
                                                   
2026-01-16 15:12:17.626 T:1117939   error <general>: [debug] [youtube] Forcing "main" player JS variant for player b95b0e7a
                                                           original url = /s/player/b95b0e7a/player_es6.vflset/en_US/base.js
                                                   
2026-01-16 15:12:18.540 T:1117939   error <general>: [debug] [youtube] QFtCeGjKOxU: tv player response playability status: LOGIN_REQUIRED
                                                   
2026-01-16 15:12:19.043 T:1117939   error <general>: [debug] [youtube] QFtCeGjKOxU: Detected experiment to bind GVS PO Token to video id.
                                                   
2026-01-16 15:12:19.045 T:1117939   error <general>: WARNING: [youtube] QFtCeGjKOxU: Some web client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
                                                   
2026-01-16 15:12:19.147 T:1117939   error <general>: [debug] Sort order given by extractor: quality, res, fps, hdr:12, source, vcodec, channels, acodec, lang, proto
                                                   
2026-01-16 15:12:19.148 T:1117939   error <general>: [debug] Formats sorted by: hasvid, ie_pref, quality, res, fps, hdr:12(7), source, vcodec, channels, acodec, lang, proto, size, br, asr, vext, aext, hasaud, id
                                                   
2026-01-16 15:12:19.169 T:1117939   error <general>: [debug] Default format spec: bestvideo*+bestaudio/best
                                                   
2026-01-16 15:12:19.351 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 160 - 256x144 (144p, ANDR-S) to DASH manifest
2026-01-16 15:12:19.591 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 278 - 256x144 (144p, ANDR-S) to DASH manifest
2026-01-16 15:12:19.863 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 394 - 256x144 (144p, ANDR-S) to DASH manifest
2026-01-16 15:12:20.071 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 133 - 426x240 (240p, ANDR-S) to DASH manifest
2026-01-16 15:12:20.409 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 242 - 426x240 (240p, ANDR-S) to DASH manifest
2026-01-16 15:12:20.646 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 395 - 426x240 (240p, ANDR-S) to DASH manifest
2026-01-16 15:12:20.864 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 134 - 640x360 (360p, ANDR-S) to DASH manifest
2026-01-16 15:12:21.086 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 243 - 640x360 (360p, ANDR-S) to DASH manifest
2026-01-16 15:12:21.262 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 396 - 640x360 (360p, ANDR-S) to DASH manifest
2026-01-16 15:12:21.464 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 135 - 854x480 (480p, ANDR-S) to DASH manifest
2026-01-16 15:12:21.694 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 244 - 854x480 (480p, ANDR-S) to DASH manifest
2026-01-16 15:12:21.877 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 397 - 854x480 (480p, ANDR-S) to DASH manifest
2026-01-16 15:12:22.641 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 136 - 1280x720 (720p, ANDR-S) to DASH manifest
2026-01-16 15:12:23.032 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 247 - 1280x720 (720p, ANDR-S) to DASH manifest
2026-01-16 15:12:23.236 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 398 - 1280x720 (720p, ANDR-S) to DASH manifest
2026-01-16 15:12:23.437 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 137 - 1920x1080 (1080p, ANDR-S) to DASH manifest
2026-01-16 15:12:23.756 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 248 - 1920x1080 (1080p, ANDR-S) to DASH manifest
2026-01-16 15:12:24.318 T:1117939    info <general>: plugin.video.sendtokodi: Added video stream 399 - 1920x1080 (1080p, ANDR-S) to DASH manifest
2026-01-16 15:12:24.573 T:1117939    info <general>: plugin.video.sendtokodi: Added audio stream 251 - audio only (medium, ANDR-S) to DASH manifest
2026-01-16 15:12:24.574 T:1117939    info <general>: plugin.video.sendtokodi: Picked DASH with custom manifest
2026-01-16 15:12:24.575 T:1117939    info <general>: plugin.video.sendtokodi: creating list item for url http://127.0.0.1:38929/manifest.mpd
2026-01-16 15:12:24.619 T:1117939    info <general>: CPythonInvoker(0, /home/gdr/.kodi/addons/plugin.video.sendtokodi/service.py): waiting on thread 129895606933184
2026-01-16 15:12:24.636 T:1117991   error <general>: 127.0.0.1 - - [16/Jan/2026 15:12:24] "HEAD /manifest.mpd HTTP/1.1" 200 -
                                                   
2026-01-16 15:12:24.642 T:1117862    info <general>: VideoPlayer::OpenFile: plugin://plugin.video.sendtokodi/?https://www.youtube.com/watch?v=QFtCeGjKOxU
2026-01-16 15:12:24.643 T:1117991   error <general>: 127.0.0.1 - - [16/Jan/2026 15:12:24] "HEAD /manifest.mpd HTTP/1.1" 200 -
                                                   
2026-01-16 15:12:24.643 T:1117992    info <general>: Creating InputStream
2026-01-16 15:12:24.650 T:1117992   error <general>: CVideoPlayer::OpenInputStream - error opening [plugin://plugin.video.sendtokodi/?https://www.youtube.com/watch?v=QFtCeGjKOxU]
2026-01-16 15:12:24.650 T:1117992    info <general>: CVideoPlayer::OnExit()
2026-01-16 15:12:24.650 T:1117992    info <general>: ADDON: Dll Destroyed - InputStream Adaptive
2026-01-16 15:12:24.651 T:1117917    info <general>: Deleting settings information for files plugin://plugin.video.sendtokodi/?https://www.youtube.com/watch?v=QFtCeGjKOxU
2026-01-16 15:12:24.752 T:1117862    info <general>: Loading skin file: DialogConfirm.xml, load type: KEEP_IN_MEMORY
2026-01-16 15:12:24.754 T:1117862    info <general>: CVideoPlayer::CloseFile()
2026-01-16 15:12:24.755 T:1117862    info <general>: VideoPlayer: waiting for threads to exit
2026-01-16 15:12:24.755 T:1117862    info <general>: VideoPlayer: finished waiting

@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

I vibe coded a solution but struggling with pushing to the PR. Basically Claude found out that special characters aren't xml-encoded in DASH manifest.

@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

Sorry I don't know how else to push here, I'm unable to push to this branch and it's a trivial change.

diff --git a/addon.xml b/addon.xml
index 9edc7c89..78b4032e 100644
--- a/addon.xml
+++ b/addon.xml
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<addon id="plugin.video.sendtokodi" name="SendToKodi" version="2025011215" provider-name="firsttris">
+<addon id="plugin.video.sendtokodi" name="SendToKodi" version="202601161520" provider-name="firsttris">
   <requires>
     <import addon="xbmc.python" version="3.0.0" />
     <import addon="script.module.inputstreamhelper" version="0.4.2" />
diff --git a/dash_builder.py b/dash_builder.py
index 32103ca7..6882f78c 100644
--- a/dash_builder.py
+++ b/dash_builder.py
@@ -4,6 +4,7 @@ from io import BytesIO
 from xml.etree.ElementTree import ElementTree, Element, SubElement, Comment
 from threading import Thread
 from http.server import BaseHTTPRequestHandler, HTTPServer
+from xml.sax.saxutils import escape
 
 def _webm_decode_int(byte):
     # Returns size and value
@@ -97,7 +98,9 @@ def _iso8601_duration(secs):
     return "P{}DT{}H{}M{}S".format(int(d), int(h), int(m), s)
 
 def transform_url(url):
-    return url.replace('&', '/').replace('?', '/').replace('=', '/')
+    # Properly escape XML special characters in URLs
+    # This ensures the manifest remains valid XML while preserving all query parameters
+    return escape(url, quote=False)
 
 
 class Manifest():

@firsttris

Copy link
Copy Markdown
Owner Author

good work mate!

i applied your fix 91220eb

is everything working, do you think we can ship it?

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds automatic Deno JavaScript runtime integration to SendToKodi to enable proper YouTube extraction with yt-dlp. Modern yt-dlp requires a JavaScript runtime for YouTube video extraction, and this implementation automatically downloads and configures Deno (~100MB) on first use, with fallback options for manual installation.

Changes:

  • Implemented automatic Deno binary download and management system with platform detection
  • Added configuration settings for Deno auto-download and YouTube JS warning suppression
  • Fixed HTTP header handling in DASH manifest generation and non-ISA streams to prevent 403 errors

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
lib/deno_manager.py Core Deno management module with download, detection, and configuration
service.py Integration with yt-dlp, Deno configuration, and improved HTTP header handling
resources/settings.xml Added settings for Deno auto-download and JS warning suppression
resources/language/resource.language.en_gb/strings.po Language strings for new settings
dash_builder.py Fixed XML escaping and added HTTP headers support for DASH manifest generation
docs/DENO_INTEGRATION.md Comprehensive documentation for Deno integration
docs/DEVELOPMENT.md Added reference to Deno integration documentation
README.md Added YouTube/Deno support information
test_deno_manager.py Test script for Deno manager functionality
example_deno_usage.py Example usage with yt-dlp
verify_integration.sh Bash script to verify integration completeness
changelog.txt Version 100.0.1 changelog
.gitignore Added Deno-related ignore patterns
Comments suppressed due to low confidence (1)

service.py:236

  • Variable 'f' is out of scope here. The loop variable 'f' from the for loop at line 158 is not available in this context (line 236). Should use 'filtered_format.get('http_headers')' instead.
            headers = f.get('http_headers')

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/DENO_INTEGRATION.md
```python
{
'js_runtimes': {
'deno': {'location': '/path/to/deno'}

Copilot AI Jan 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key should be 'path', not 'location'. According to yt-dlp's implementation in lib/yt_dlp/YoutubeDL.py (line 544 and 880), the correct configuration key is 'path'. The actual implementation in lib/deno_manager.py line 325 correctly uses 'path'.

Copilot uses AI. Check for mistakes.
Comment thread docs/DENO_INTEGRATION.md Outdated
Comment thread lib/deno_manager.py Outdated
Comment thread verify_integration.sh
Comment thread docs/DENO_INTEGRATION.md

You don't need to configure these manually - yt-dlp passes the required permissions when executing Deno. The integration is transparent and secure.

## For Developers

Copilot AI Jan 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The heading '## For Developers' appears twice in the document (lines 88 and 117). The first occurrence at line 88 should likely be a different heading or merged with the second section to avoid duplicate headings.

Suggested change
## For Developers
## Developer Resources

Copilot uses AI. Check for mistakes.
Comment thread lib/deno_manager.py
import zipfile
import tarfile
import tempfile
import shutil

Copilot AI Jan 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'shutil' is not used.

Suggested change
import shutil

Copilot uses AI. Check for mistakes.
Comment thread lib/deno_manager.py
Comment on lines +25 to +27
from urllib.error import URLError
except ImportError:
from urllib2 import urlopen, Request, URLError

Copilot AI Jan 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'URLError' is not used.

Suggested change
from urllib.error import URLError
except ImportError:
from urllib2 import urlopen, Request, URLError
except ImportError:
from urllib2 import urlopen, Request

Copilot uses AI. Check for mistakes.
Comment thread lib/deno_manager.py
Comment on lines +25 to +27
from urllib.error import URLError
except ImportError:
from urllib2 import urlopen, Request, URLError

Copilot AI Jan 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'URLError' is not used.

Suggested change
from urllib.error import URLError
except ImportError:
from urllib2 import urlopen, Request, URLError
except ImportError:
from urllib2 import urlopen, Request

Copilot uses AI. Check for mistakes.
Comment thread lib/deno_manager.py
# Clean up the archive
try:
os.remove(archive_path)
except:

Copilot AI Jan 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except block directly handles BaseException.

Suggested change
except:
except OSError:

Copilot uses AI. Check for mistakes.
Comment thread lib/deno_manager.py
# Clean up the archive
try:
os.remove(archive_path)
except:

Copilot AI Jan 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'except' clause does nothing but pass and there is no explanatory comment.

Suggested change
except:
except OSError:
# Ignore errors while removing temporary archive file

Copilot uses AI. Check for mistakes.
@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

I can't explain how, but it works (with the most blurry resolution) even though the Python version in Kodi is old enough to throw this exception:

2026-01-16 18:30:22.219 T:1144426   debug <general>: [script.module.inputstreamhelper] inputstream.adaptive 20.3.18 is installed and enabled.
2026-01-16 18:30:22.238 T:1144426    info <general>: plugin.video.sendtokodi: Failed to add DASH video stream 160 - 256x144 (144p): escape() got an unexpected keyword argument 'quote'
2026-01-16 18:30:22.238 T:1144426    info <general>: plugin.video.sendtokodi: Failed to add DASH video stream 278 - 256x144 (144p): escape() got an unexpected keyword argument 'quote'
2026-01-16 18:30:22.238 T:1144426    info <general>: plugin.video.sendtokodi: Failed to add DASH video stream 394 - 256x144 (144p): escape() got an unexpected keyword argument 'quote'
2026-01-16 18:30:22.238 T:1144426    info <general>: plugin.video.sendtokodi: Failed to add DASH video stream 133 - 426x240 (240p): escape() got an unexpected keyword argument 'quote'
2026-01-16 18:30:22.238 T:1144426    info <general>: plugin.video.sendtokodi: Failed to add DASH video stream 242 - 426x240 (240p): escape() got an unexpected keyword argument 'quote'
2026-01-16 18:30:22.238 T:1144426    info <general>: plugin.video.sendtokodi: Failed to add DASH video stream 395 - 426x240 (240p): escape() got an unexpected keyword argument 'quote'
2026-01-16 18:30:22.238 T:1144426    info <general>: plugin.video.sendtokodi: Failed to add DASH video stream 134 - 640x360 (360p): escape() got an unexpected keyword argument 'quote'
...

To make things stranger, if I remove the parameter and try playing a stream this way, it doesn't play because:

2026-01-16 18:34:49.718 T:1145108   debug <general>: ADDON: Dll Initializing - InputStream Adaptive
2026-01-16 18:34:49.718 T:1145108   error <general>: IAddonInstanceHandler::CreateInstance: inputstream.adaptive returned bad status "Permanent failure" during instance creation
2026-01-16 18:34:49.718 T:1145108   error <general>: CVideoPlayer::OpenInputStream - error opening [plugin://plugin.video.sendtokodi/?https://youtu.be/3OAiOfCcYFM]

So somehow it only works without these sources!?

@gjedeer

gjedeer commented Jan 16, 2026

Copy link
Copy Markdown

So, looking at the code, the way claude fixed the playback, was by effectively disabling the DASH builder? xD I just disabled DASH in settings and it plays now, with the "quote" argument removed.

firsttris and others added 5 commits January 16, 2026 20:11
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@firsttris

Copy link
Copy Markdown
Owner Author

i did some testing, installed kodi from flatpak installed my extension. send a youtube video with high quality. and it just works without deno.

it plays the highest resolution vp9 2560x1350,

@firsttris firsttris closed this Jan 17, 2026
@glogiotatidis

Copy link
Copy Markdown
Contributor

@firsttris My kodi instance cannot access videos without deno. I had claude patch sendtokodi locally with deno and it works. Are you interested to revive this PR or I can also PR a fresh one if you are willing to review

@firsttris

Copy link
Copy Markdown
Owner Author

@glogiotatidis yes sure please create PR, can you ellaborate in which cases you need deno?

@glogiotatidis

Copy link
Copy Markdown
Contributor

I's trying to play this for example https://www.youtube.com/watch?v=1_Vlcr-ihkY

@brevilo

brevilo commented Mar 17, 2026

Copy link
Copy Markdown
Collaborator

@glogiotatidis yes sure please create PR, can you ellaborate in which cases you need deno?

Isn't deno generally required by the latest yt-dlp?

@firsttris

Copy link
Copy Markdown
Owner Author

Last time I checked, it was still working without Deno, but it now seems to be deprecated:

2026-03-18 06:29:33.040 T:78      error <general>: WARNING: [youtube] No supported JavaScript runtime could be found. Only deno is enabled by default; to use another runtime add  --js-runtimes RUNTIME[:PATH]  to your command/config. YouTube extraction without a JS runtime has been deprecated, and some formats may be missing. See  https://github.com/yt-dlp/yt-dlp/wiki/EJS  for details on installing one
                                                   
2026-03-18 06:29:33.126 T:78      error <general>: ERROR: [youtube] 1_Vlcr-ihkY: This video is not available
                                                   
2026-03-18 06:29:33.127 T:78      error <general>: plugin.video.sendtokodi: Traceback (most recent call last):

@glogiotatidis could you share the changes you made? I can then publish a new version.

@glogiotatidis

Copy link
Copy Markdown
Contributor

Here you go #168.

This is vibe coded but tested on rpi4 / libreelec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants