Skip to content

Capture upstream HLS PROGRAM-DATE-TIME per segment and emit atomic per-channel PDT file on .aac requests#79

Merged
paul-1 merged 6 commits into
mainfrom
copilot/implement-upstream-pdt-capture
Apr 19, 2026
Merged

Capture upstream HLS PROGRAM-DATE-TIME per segment and emit atomic per-channel PDT file on .aac requests#79
paul-1 merged 6 commits into
mainfrom
copilot/implement-upstream-pdt-capture

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 19, 2026

  • Triage new runtime error comment and identify root cause
  • Run baseline validation before edits
  • Fix PDT directory creation call so it works in SiriusXM package context
  • Run targeted validation to confirm no regression
  • Run final parallel validation
  • Reply to PR comment with commit hash
Original prompt

Repository: paul-1/plugin-SiriusXM

Goal
Implement capturing upstream HLS #EXT-X-PROGRAM-DATE-TIME values per segment and, when a client requests a segment (.aac), atomically write the actual upstream program date/time for that segment to a temp file cache_dir/pdt_<channel_id>.txt so another process can track current playlist time.

Context

  • File to modify: Plugins/SiriusXM/Bin/sxm.pl (main branch).
  • Segment requests are handled in handle_http_request for paths matching \.aac$, which calls $sxm->get_cached_segment($segment_path, $channel_id) when channel_id can be extracted.
  • Playlist parsing currently extracts segments via extract_segments_from_playlist($content, $channel_id) by scanning for #EXTINF then consuming the following .aac URI; it does NOT currently parse #EXT-X-PROGRAM-DATE-TIME.
  • Requirement: retain upstream program date/time (do not synthesize).

Required changes

  1. Add data structure to store upstream PDT per segment.

    • In the SiriusXM object (constructor new), add a hash (e.g. segment_pdt => {}) keyed by channel_id then segment URI.
  2. Update extract_segments_from_playlist($content, $channel_id) to parse upstream PDT.

    • Track the most recent #EXT-X-PROGRAM-DATE-TIME:<iso8601> line encountered.
    • When an .aac segment URI is captured (the line after #EXTINF:), also store the PDT for that segment in the mapping: $self->{segment_pdt}{$channel_id}{$segment_uri} = $current_pdt.
    • Ensure mapping remains correct even if PDT appears before #EXTINF (common). Do not overwrite segment mapping later.
  3. Add helper to write the current segment’s PDT to disk.

    • Implement something like write_segment_pdt_file($channel_id, $segment_path) in the SiriusXM package.
    • Determine cache_dir as the directory containing $main::CONFIG{cookiefile} (same approach used elsewhere for channels.json/server_state.json). Use dirname and File::Spec->catfile.
    • Write to ${cache_dir}/pdt_<channel_id>.txt.tmp then rename to ${cache_dir}/pdt_<channel_id>.txt for atomic update.
    • File content should be exactly the upstream ISO8601 string plus newline.
    • If there is no PDT for this segment, do not write a file (log at DEBUG/TRACE only).
  4. Call PDT file writer on each segment request.

    • In get_cached_segment($segment_path, $channel_id), after tracking last requested segment ($self->{last_segment}{$channel_id} = $segment_path;), call the writer so it runs whether segment is served from cache or fetched.
  5. Safety/robustness

    • Do not crash if cookiefile is unset; simply skip writing and log debug.
    • Avoid leaking sensitive info in logs.

Acceptance criteria

  • When playlist contains #EXT-X-PROGRAM-DATE-TIME, and a client later requests a segment present in that playlist, the code writes cache_dir/pdt_<channel_id>.txt with that exact upstream value.
  • Updates are atomic via temp file + rename.
  • No behavior change to segment bytes returned to client.

Files

  • Modify: Plugins/SiriusXM/Bin/sxm.pl

Reference
image1

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: When caching the segments, can we also include and entry containing #EXT-X-PROGRAM-DATE-TIME with the segment

Assistant: Yes — you can include #EXT-X-PROGRAM-DATE-TIME “with the segment”, but it shouldn’t be stored inside the binary segment cache entry. Instead, store it as metadata alongside the cached segment, and then emit it in the generated .m3u8 right before the corresponding #EXTINF/URI line.

Why this way (fits your current code)

Right now cache_next_segment() only caches raw bytes:

  • it fetches segment bytes via get_segment($segment_path)
  • then stores: $self->{segment_cache}->{$channel_id}->{$segment_path} = $segment_data; citeturn1search1

There’s no existing handling of #EXT-X-PROGRAM-DATE-TIME in the codebase (no matches), so the playlist parser/generator would need to be extended anyway. citeturn1search0

Suggested shape

Keep segment bytes as-is, and add another structure, e.g.:

  • $self->{segment_program_date_time}->{$channel_id}->{$segment_path} = $iso8601_time;

Then, wherever you build the cached playlist (playlist_cache / playlist generation code), when outputting each segment line:

  1. if PDT exists for that segment, emit:
    • #EXT-X-PROGRAM-DATE-TIME:<value>
  2. then emit the existing #EXTINF and segment URI.

One key question (so it’s correct)

Do you want the #EXT-X-PROGRAM-DATE-TIME value to be:

  1. Copied from the upstream playlist (best, if SiriusXM provides it), or
  2. Synthesized locally (e.g., “now minus N*EXTINF” when parsing), if upstream does not provide it?

If you tell me which one you want, I can point you to the exact playlist parse/generation area in sxm.pl that needs to be updated and what to store per segment.

User: I want to retain the upstream program date. The client will still be requesting ...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Add capturing upstream HLS #EXT-X-PROGRAM-DATE-TIME values Capture upstream HLS PROGRAM-DATE-TIME per segment and emit atomic per-channel PDT file on .aac requests Apr 19, 2026
Copilot AI requested a review from paul-1 April 19, 2026 17:06
Copy link
Copy Markdown
Owner

@paul-1 paul-1 left a comment

Choose a reason for hiding this comment

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

@copilot when clearing the channel state, we should delete the pdt file from the cache.

But is there a way do this without writing the disk every 10s

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 19, 2026

@copilot when clearing the channel state, we should delete the pdt file from the cache.

But is there a way do this without writing the disk every 10s

Implemented in bf85f07: clear_channel_cache now deletes pdt_<channel_id>.txt (and .tmp) from the cache dir. I also reduced disk churn by skipping PDT writes when the upstream PDT value is unchanged and the file already exists, so it won’t rewrite on every segment interval.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/apt/methods/https /usr/lib/apt/methods/https (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from paul-1 April 19, 2026 17:28
@paul-1
Copy link
Copy Markdown
Owner

paul-1 commented Apr 19, 2026

@copilot lets move this file storage to $TMPDIR/siriusxm/pdt_<channel_id>.txt

tmp directories are often ramdisks and we do not have to worry about frequent writes.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 19, 2026

@copilot lets move this file storage to $TMPDIR/siriusxm/pdt_<channel_id>.txt

tmp directories are often ramdisks and we do not have to worry about frequent writes.

Done in c31b477. PDT files now read/write at $TMPDIR/siriusxm/pdt_<channel_id>.txt (fallback: TEMP, then /tmp), and clear_channel_cache removes the .txt and .tmp files from that same location. No UI changes in this update.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/apt/methods/https /usr/lib/apt/methods/https (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Copy Markdown
Owner

@paul-1 paul-1 left a comment

Choose a reason for hiding this comment

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

@copilot getting this error

[19.04.2026 13:38:39.757] DEBUG SiriusXM::write_segment_pdt_file:2240: Could not create PDT directory /tmp/siriusxm for channel 9450: Undefined subroutine &SiriusXM::make_path called at /opt/slimserver/Cache/InstalledPlugins/Plugins/SiriusXM/Bin/sxm.pl line 2236.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 19, 2026

@copilot getting this error

[19.04.2026 13:38:39.757] DEBUG SiriusXM::write_segment_pdt_file:2240: Could not create PDT directory /tmp/siriusxm for channel 9450: Undefined subroutine &SiriusXM::make_...

Fixed in cabadac: write_segment_pdt_file now calls File::Path::make_path(...) explicitly, so $TMPDIR/siriusxm creation works from the SiriusXM package and avoids the Undefined subroutine &SiriusXM::make_path error. No UI changes in this update.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/apt/methods/https /usr/lib/apt/methods/https (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from paul-1 April 19, 2026 17:44
@paul-1 paul-1 marked this pull request as ready for review April 19, 2026 17:47
@paul-1 paul-1 merged commit ae1f162 into main Apr 19, 2026
1 check passed
@paul-1 paul-1 deleted the copilot/implement-upstream-pdt-capture branch April 19, 2026 17:47
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