Skip to content

fix(m3u): support multiple URL lines under a single #EXTINF - #746

Merged
stackia merged 6 commits into
mainfrom
cursor/m3u-multi-url-per-extinf-bd32
Sep 5, 2026
Merged

fix(m3u): support multiple URL lines under a single #EXTINF#746
stackia merged 6 commits into
mainfrom
cursor/m3u-multi-url-per-extinf-bd32

Conversation

@stackia

@stackia stackia commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Closes #740

Problem

An M3U entry written as one #EXTINF followed by several URL lines lost every URL except the first:

#EXTINF:-1 group-title="分组1",Channel 3
https://example.com/stream3$线路1
https://example.com/stream3$线路2

Both layers were affected:

  • src/m3u.c: in_entry was reset after the first URL, so the second URL was silently dropped from the transformed /playlist.m3u and no service was created for it.
  • web-ui/src/lib/m3u-parser.ts: currentExtinf was reset after the first URL, so the player parsed such an entry as a single-source channel.

Fix

  • Server: keep the entry open after the first URL. Each additional URL-looking line (scheme://... or /path) under the same #EXTINF gets its own service path (.../Channel/label, or .../Channel/2, /3 when unlabelled). The transformed playlist preserves the input shape: the #EXTINF line is written once and the rewritten URLs follow it; entries that repeat #EXTINF stay repeated. The blank separator between entries is deferred until the next tag so single-URL output is byte-identical to before. catchup-source lives on the one #EXTINF line, so the catchup service is created and rewritten once (against the first source). Stray non-URL text after an entry is still ignored.
  • Web UI: consecutive URL lines under one #EXTINF are appended as sources of the same channel.
  • Docs (zh source + en translation): one #EXTINF followed by multiple URL lines is the documented way to declare a multi-source channel; the example output shows the converted playlist keeping that structure.

Tests

  • New vitest cases for parseM3U (multi-URL entry, mixing with repeated #EXTINF, catchup propagation, orphan URL lines).
  • New e2e class TestM3UMultiURLPerEXTINF in e2e/test_m3u.py: shape preserved with every URL rewritten, unlabelled URLs get unique paths, repeated-#EXTINF input stays repeated, catchup rewritten once for a multi-URL entry, stray text ignored.
  • Full e2e suite (601 passed), pnpm run lint, tsc --noEmit, pnpm run web-ui:test, and pnpm run docs:build pass locally; all CI checks green.

Manual check

Web player against the fixed binary with the issue's playlist form: Channel 3 is listed once, its source menu shows 线路1 / 线路2, and an unlabelled three-URL entry shows Source 1 / Source 2 / Source 3.

Channel list shows Channel 3 once
Channel 3 source menu with 线路1 and 线路2
Channel 5 source menu with three sources

Open in Web Open in Cursor 

cursoragent and others added 3 commits September 5, 2026 01:05
A #EXTINF followed by several URL lines describes one channel with multiple
sources. The converter only consumed the first URL and silently dropped the
rest, so such channels lost all but one source in the transformed playlist.
Keep the entry open after the first URL and re-emit the EXTINF line for each
additional URL-looking line, so every source gets its own service path.

Closes #740

Co-authored-by: Stackie Jia <jsq2627@gmail.com>
…hannel sources

The player parser reset the pending EXTINF after the first URL line, so a
second URL under the same #EXTINF was ignored instead of becoming another
source of the channel.

Co-authored-by: Stackie Jia <jsq2627@gmail.com>
Co-authored-by: Stackie Jia <jsq2627@gmail.com>
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Documentation preview

The documentation preview has been deployed for this pull request.

cursoragent and others added 3 commits September 5, 2026 01:13
…lti-source form

Co-authored-by: Stackie Jia <jsq2627@gmail.com>
Write the EXTINF line once and list the rewritten URLs directly beneath it
instead of re-emitting EXTINF per URL, so the transformed playlist mirrors
the source playlist. The blank separator between entries is deferred until
the next tag so single-URL output is unchanged.

Co-authored-by: Stackie Jia <jsq2627@gmail.com>
…URLs

Co-authored-by: Stackie Jia <jsq2627@gmail.com>
@stackia
stackia marked this pull request as ready for review September 5, 2026 02:07
@cursor

cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_e53f5288-b28c-4425-8c03-5d0fb3ff2e6f)

@stackia
stackia merged commit dacb047 into main Sep 5, 2026
12 checks passed
@stackia
stackia deleted the cursor/m3u-multi-url-per-extinf-bd32 branch September 5, 2026 02:07
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.

网页播放器不支持一个频道多个源吗?

2 participants