All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Nothing yet
1.13.0 - 2026-08-11
- Optional mode field on
timecc608, whose value is now<channel>-<lang>[-<mode>[-<modifier>]], choosing the CTA-608 caption mode:paint(the default),pop,pop-sc,roll2orroll3. Paint-on and roll-up type the caption out two characters per frame — paint-on onto a screen cleared at the start of each second, roll-up onto the base row of a 2- or 3-row window that scrolls the earlier lines up — and both keep every caption inside the segment that carries it, so segments stay independently decodable for a client that starts, seeks or joins mid-stream. Roll-up is limited to 2 or 3 rows because the caption's own lines put its base row at row 3. Generated by go-608 v0.9.0'sgenerate.BuildUnitPaintCuesandBuildUnitRollUpCues.
timecc608defaults to paint-on instead of pop-on, so by default no segment's captions depend on its neighbours. Pop-on remains available as-pop, with-pop-scfor the self-contained placement; a bare-sc(which used to ask for that) is rejected with a message pointing at-pop-sc.- The
timecc608language must be a three-letter ISO 639-2 code (eng,swe), the form the SCTE 214-1 CEA-608 accessibility descriptor value is defined in, and the only place this option's language is used. RFC 5646 tags that DASH's@langaccepts —en,en-US,zh-Hans— were previously allowed through intovalue="CC1=..."and are now rejected. With the language a single field, an unknown mode or modifier is reported instead of being read as part of it. - mp4ff dependency bumped to v0.55.0 and go-608 to v0.9.0
- The CTA-608 cue scheduling for
timecc608is back to go-608's per-unit builders, whose v0.8.0generate.Unit(number, start time and frame count as independent inputs) andWithFlipAtCueStartcover both pop-on flip placements livesim2 needs, so the local copy of that scheduler is gone. Same bytes on the wire. - A
timecc608caption cue is never shorter than a second now that go-608 v0.9.0 divides a segment down into whole periods: a segment whose duration is not a multiple of a second, e.g. 1.92 s, gets one cue covering it instead of two shorter ones. Segments of 2 s and 2.002 s are unaffected.
- In-band CTA-608 captions in pop-on mode (
timecc608_CC1-eng-pop) are now displayed over exactly the interval their text names, instead of appearing 0.6-0.75 s into it. Each cue's flip rides its cue's first frame, with the build sent over the preceding frames. Such captions consequently span segment boundaries, which costs a client that starts or seeks mid-stream its first cue period — see the README. The new default mode, paint-on, has neither problem.
1.12.0 - 2026-07-23
- AV1 video support: assets with
av01/av1Csample entries are recognized as video and served, and AV1 segments can be encrypted on the fly for bothcencandcbcsschemes. Per-segment common-encryption protection ranges (clear OBU/tile headers, protected tile data) are computed by mp4ff viamp4.EncryptFragments, which builds a fresh AV1 frame-header decoder per segment so concurrent requests are race-free. A newtestpic_2s_av1test asset (AV1 1280x720@25 at 400 and 600 kbps, using moqlivemock content, + AAC) exercises the path. - In-band CTA-608 (CEA-608) closed captions: the
timecc608_<channel>-<lang>URL option (e.g.timecc608_CC1-eng) injects a caption into the AVC/HEVC video elementary stream itself, showing a ticking UTC clock and the segment number on channel CC1, frame-accurate to wall-clock. The caption is built by the shared go-608generate.BuildUnitCueshelper (one self-contained pop-on cue per ~second, distributed one 608 pair per frame in presentation order) and carried asuser_data_registered_itu_t_t35SEI on every frame, on both the default whole-segment path and the low-latency chunked path. The video AdaptationSet is advertised with aurn:scte:dash:cc:cea-608:2015Accessibilitydescriptor. The option cannot be combined with encryption and is rejected (HTTP 400) for assets that already carry CEA-608/708 captions (detected from the source MPD descriptor or existingcc_dataSEI at scan time). Surfaced in the/urlgen/form. - New test asset
testpic_2s/cea608.mpd(video representationV300_with_cc1_and_cc3,CC1=eng;CC3=swe) carrying real in-band CEA-608 captions, used as the "already captioned" reject case.
- Bumped
github.com/Eyevinn/mp4ffto v0.54.0 for AV1 common-encryption (cenc/cbcs) support and the immutable-InitProtectData/EncryptFragmentsAPI; segment encryption now callsmp4.EncryptFragmentsper segment instead of loopingEncryptFragment.
1.11.0 - 2026-06-30
- DASH Content Steering (ISO/IEC 23009-1 6th ed. §K.3.6, ETSI TS 103 998): the
steer_URL option advertises several service locations ("CDNs") that point back to this server and adds a<ContentSteering>element; the steering endpoint returns aPATHWAY-PRIORITYmanifest with a configurablettl=andmode=trigger(hold until switched) ormode=rotate. Per-session, per-CDN segment requests are tracked and switchable via the/api/steering/…API and a live/steering/session_statusmonitor page; client steering messages (_DASH_pathway/_DASH_throughput) are verified and off-pathway clients flagged. An optionalcsid_<group>token groups sessions under one shared decision. The/urlgen/form has a Content Steering section and the index page links to the monitor. - DASH XLink for multi-period: the
xlink_1URL option activates the replacement of completed past periods elements with remote elements using XLink elements withxlink:href="onRequest". The XLink urls for each completed period target the same endpoint as the manifest and adding the?period=<period_id>query parameter, which is interpreted by livesim2 to return the corresponding Period element.
- URL generator: DRM options now follow the selected asset and are disabled for pre-encrypted assets.
- The SGAI and Content Steering live monitor pages (
/sgai/session_status,/steering/session_status) now follow the system light/dark setting (via Pico CSS) like the other web pages, with theme-aware status colours for legibility on both backgrounds, while staying full-width and compact for their denser tables. Their shared styles and JS helpers (esc/fmtTime/setDot) are factored intostatic/session_status.cssandstatic/session_status_common.js. - Migrated the HTML web pages (welcome, assets, VoD assets, URL generator, SGAI
session status) from Go's
html/templateto type-safe templ components (*.templ→ generated*_templ.go). Thetext/templateXML subtitle templates (stpptime.xml,stpptimecue.xml) are unchanged. Building now runstempl generate(seemake templ); amake templ-checktarget and a pre-commit hook (triggered by both*.templand*_templ.gochanges) keep the generated code in sync, and the generated*_templ.gofiles are excluded fromgolangci-lint. - Updated
github.com/go-chi/chi/v5from v5.2.2 to v5.2.4.
- cmaf-ingest-receiver tests: replaced fixed
time.Sleepwaits for the receiver's asynchronous writes with polling (EventuallyWithT), fixing intermittent failures on the Windows CI runner. - Hardened the
esc()helper on the SGAI session-status page (added in v1.10.0) to also escape"and', so values interpolated into double-quoted HTML attributes cannot break out of the attribute (attribute XSS); matches the same hardening on the content-steering status page.
1.10.0 - 2026-06-15
- Upgraded the project to Go 1.25 (
go.mod, GitHub Actions workflows, and theDockerfilebuild stage). - Default
--playurlreference player switched fromdash.js/latesttodash.js/nightly, sincelatestcurrently ignores the MPD URL parameters passed via?mpd=.
- Server-Guided Ad Insertion (SGAI) per DASH Ed.6 Alternative-MPD:
sgai_URL option injects Replace events (urn:mpeg:dash:event:alternativeMPD:replace:2025) with Annex I RequestParam;/sgai/adsreturns a personalized List MPD for an interest-steered request (interest steering, per-session rotation within a match, duration fit); ad creatives are SPS VoD assets under<vodroot>/ads/with optionalads.jsontags;/sgai/beaconrecords impression + quartile beacons; session store with/api/sgai/ads,/api/sgai/sessions[/{sid}]APIs and a live/sgai/session_statusmonitor page. - Periodic SGAI ad breaks:
sgai_p<period>:<dur>schedules a break at every wall-clock multiple of the period (e.g.p60:20= 20 s at every full UTC minute), with windowed event signaling and stable per-occurrence ids; late joiners land mid-break. - Generated "AD BREAK" countdown slate served on the video track inside SGAI break
windows: encoded with hi264 against the representation's own SPS/PPS (IDR per second
- P_Skip), mirroring the replaced segment's frame timing and per-sample sizes (filler-NALU padding) so frame rate and bitrate match; audio untouched.
- An ad pod is only generated for an interest-steered request: with no
interests=(the default — e.g. a plain stream with no sessionId/interests) or interests that match no ad,/sgai/adsanswers 404 and the break stays unfilled, so the viewer keeps the underlying AD BREAK slate (the base ad). Cache-Control: no-storeon ad creatives (/vod/ads/*) and List MPD responses.- SGAI section on the urlgen page; SGAI mentioned on the landing page and in the OpenAPI description; ad creatives filtered out of the urlgen asset list.
- Two minimal example ad creatives bundled under the test vodroot
(
testdata/assets/ads/):train_ad(travel) andgotland_runt_ad(sailing, boats), each a single 640×360 representation plus audio, so SGAI works out of the box andinterests=travel,sailingyields a two-ad pod. - README section documenting SGAI: the
sgai_schedule option, ad creatives andinterests/sessionIdpersonalization, the pod-selection and AD BREAK slate behavior, and the monitoring endpoints. - Honor the
X-Forwarded-Protoheader (set by a fronting proxy / CDN) when constructing the scheme in MPDLocationandBaseURLelements. Onlyhttpandhttpsare accepted; other values fall back to local TLS detection.
- Misleading
--writerepdatadescription in the CLI help and README: the flag always (re)generates and overwrites representation metadata, but was documented as "if not present". Corrected the help/README text and added the missing--writemissingrepdataflag to the README option list (use it to write only missing files). Behavior unchanged. - IV reuse across fragments in
cencencryption mode by chaining the IV returned bymp4.EncryptFragment(Issue #295)
--schemeCLI flag. It was never read by the server and had no effect. Use--host=https://example.com(full scheme://host) for a hard override, or rely onX-Forwarded-Protofrom your proxy.
1.9.0 - 2026-02-06
- VVC test content (testpic_2s_vvc)
- New
--writemissingrepdataCLI option to generate RepData files only for representations that lack them (Issue #271) - Version field in RepData structure to support future format evolution
- Support for DASH-IF Certurl ContentProtection element
- Pattern support for audio SegmentTimeline following DASH Ed. 6
- New URL options
segtimeline_pattern/andsegtimelinenr_pattern/ - URL generator page options for both pattern cases
- Documentation for CMAF Ingest
- Anchored regex for matching representation
- Security alerts from CodeQL
- Race conditions in CMAF Ingest tests
1.8.0 - 2025-09-11
- HEVC encryption support
- AC-4 audio support (including full encryption)
- MPEG-H audio support (including full encryption)
- AC-3 and EC-3 full encryption support
- Support for CMAF-compliant audio edit list
- Documented the CMAF edit list support for both audio and video
- Minimal Go version increased to 1.23
- Updated dash-mpd to v0.13.0 (Full DASH Ed. 6 support)
- Updated mp4ff to v0.50.0 (more codecs support)
- One HTTP PUT with Content-Length in cmaf-ingest
- Fixed typo in urlgen template
- Lost error reporting in initial segment parsing
- Added
Access-Control-Expose-Headerto make UTCTiming HEAD work (Issue #251)
- Test asset with varying segment duration (4s and 8s) with exact 6s average
- Described how to use Dockerfile from Github Container repository (ghcr.io)
1.7.0 - 2025-01-17
- CMAF ingest of full segments now send Content-Length header
- Basic Annex I support for announcing that MPD query parameters should be used in all video segment requests
- Verification that the MPD and the video segments carry the URL-specified query parameters
- endNumber in live MPD (Issue #235)
- urlgen page crashed when no DRM configuration
- mpd part of play URL in urlgen is now query escaped
- ContentProtect for DRMs in CPIX file with no configured LaURL
- Updated to golangci-lint v2 and fixed all remarks
- updated dependencies
1.6.0 - 2024-12-03
- On-the-fly encryption with keys from commercial DRM (Widevine and PlayReady) via CPIX document
- DRM configuration and URL generation on
urlgenpage - Unified ECCP and other DRMs using the new URL parameter
/drm_X
- CLI parameter -h for livesim2
1.5.2 - 2024-11-05
- Segment size bug for ECCP encryption (introduced in v1.5.1)
--timeoutparameter not working. Changed to--timeoutS
1.5.1 - 2024-11-01
- Better logging when loading asset representation data
- Check that pre-encrypted content has the same duration for all representations
- Test that endNumber in SegmentTemplate will limit segments used
- Automatic build of Docker Images
- Pre-encrypted content is not re-fragmented, but left as it
- Dockerfile to insert version in binary (requires full repo or tag)
1.5.0 - 2024-10-02
- Added functions and constants for CMAF file extensions in pkg/cmaf
- Short HEVC + AC-3 test content
- Generation of CMAF ingest streams with a REST-based API
- New program
cmaf-ingest-receiverthat can receive one or more CMAF ingest streams - New option
--whitelistblocksfor unlimited number of requests to some CIDR blocks - Much improved
cmaf-ingest-receiver - Link on starting page to Wiki page on preparing content
- Will now set contentType from mimeType on AdaptationSet or Representation level.
- If contentType and mimedType is not present, contentType will be set from codecs string.
- Issue with audio resegmentation.
- Go version changed to 1.22
1.4.1 - 2024-05-28
- publishTime of MPD for multiperiod with SegmentTimeline
1.4.0 - 2024-05-25
- More error logging for segment generation.
- New endpoint /version responds with livesim2 version
- Some more links in the Welcome page
- fix patch response for multiperiod segment-timeline
- fix publishTime for multiperiod SegmentTemplate with Number
1.3.1 - 2024-05-08
- correct low-latency MPD update time for SegmentTimeline
1.3.0 - 2024-04-23
- MPD Patch functionality with new
/patch_ttlURL configuration - nowDate query parameter as an alternative to nowMS for MPD and patch
- MPD Patch has Expires header equal to publishTime + ttl + 10s
- Timed stpp subtitles EBU-TT-D linePadding
- Update dependencies
1.2.2 - 2024-03-05
- Add extra CORS headers to fix ECCP key request
1.2.1 - 2024-03-04
- Correct UTCTiming schemes for http-iso and http-head
- Make urlgen fields for negative test cases easier to fill
- Fix OPTIONS for livesim2/ path
- Fix encryption of segments for representations with previous metadata
1.2.0 - 2024-02-16
- Support for DASH-IF Enhanced Clear Key Content Protection (ECCP)
- On the fly encryption for ECCP using cbcs or cenc scheme
- Make HTTP OPTIONS method work for all URLs
- Make --playurl work for general paths
- Derive and insert contentType if missing
- Remove any mehd box from init segment
- Asset lookup for case where one asset path is prefix of another
1.1.1 - 2024-01-19
- The UTCTiming output for xsdate is now the same as for ISO
- The DASH-IF content protection signaling updated to follow ECCP in IOP 5.0
1.1.0 - 2024-01-04
- UTCTiming "mode"
keepforwards UTCTiming values from VoD MPD - UTCTiming "modes"
httpisomsandhttpxsdatemsfor millisecond resolution - Support for Marlin DRM and DASH-IF ClearKey in MPD
- Default UTCTiming signaling schemeIdUri set to "urn:mpeg:dash:utc:http-xsdate:2014"
1.0.1 - 2023-11-15
- Correct contentType match for subtitles (text)
1.0.0 - 2023-10-30
- New highly configurable
statuscodeparameter for cyclic bad segment request responses - New URL parameter
trafficto simulate periodic issues with fetching segments. Supports multiple parallel BaseURLs. - Dockerfile to build a minimal Docker image with sample test content
- Upgrade to Go 1.21
- Changed logging to slog instead of zerolog. Log levels limited to DEBUG, INFO, WARN, ERROR.
- Vertical spacing for buttons on web pages
0.9.0 - 2023-10-13
- Support for audio segments not matching video duration. Audio timing follows video by resegmentation
- Test content with 29.97fps with and without audio beeps
- /debug/pprof entry for profiling
- log url and location for redirected HTTP requests
- The online player is now proxied via /player when livesim2 runs with http
- The online playURL should now including scheme
- repdata (representation data on disk) format extended with commonSampleDuration
- writerepdata option writes repdata even if existing
- added muted=true to default playURL
- HTTP 410 Gone response for segments before timeShiftBufferDepth
- limited methods in OPTIONS response
0.8.0 - 2023-09-22
- Prometheus counters and histograms for request timing
- Direct links to play assets mapped to latest dash.js with http or https scheme
- Timing-Allow-Origin header to enable more detailed timing in client
- /genurl page with URL generator supporting all URL parameters
- /reqcount page for checking requests per interval
- New option to log requests per interval to a file
- The / page has been slightly rewritten
- The /assets and /vod pages slightly changed
- The request limit interval can now be configured
- utc-timing URLs use https scheme
0.7.0 - 2023-08-24
- much improved information web pages. Extracts MPD information from
ProgramInformationinside MPDs. - Full URLs to assets is listed and can be copied to clipboard from pages
/assetsand/vod - support for
/scte35_xURL config to insert periodic SCTE-35 emsg message (1, 2, or 3 per minute) - server startup boost by loading (and writing) previously generated gzipped tar files with representation metadata
- new configuration parameters
repdatarootandwriterepdatato control this - HTTP redirect from
/livesimto/livesim2and/dash/vodto/vodfor compatibility with livesim1 - support assets with stpp subtitles in both text and image format. New test content added
- support DASH-IF thumbnails including multi-period. New test content added
- new URL parameter
timesubswvttprovides generated timing wvtt subtitles timesubsstppandtimesubswvttnow work with SegmentTimelinecontinuous_1URL parameter to signal multiperiod continuity- Automatic Let's Encrypt certificates for HTTPS for one or more domains via
domainsparameter
/ato_inf(infinite availability offset) now makes all segments in past and future available
0.6.0 - 2023-06-10
- moved list URL parameters to livesim2 wiki
- removed
schemeandurlprefixconfiguration. Now replaced withhostwhich overridesscheme://hostin all generated URLs
- new URL parameter
periodsprovides multiple periods (n <= 60 per hours, segment and period durations must be compatible) - new URL parameter
segtimelinenrturns on SegmentTimeline with$Number$addressing - new URL parameter
mupto set minimumUpdatePeriod in MPD - new URL parameter
subsstppregcan set vertical region - new URL parameter
ltgtsets latency target in milliseconds - new URL parameter
utcto set one, multiple, or zero UTCTiming methods - new functionality to handle relative start and stop times by generating a Location element
- new config parameters
schemeandhostto be used in generated Location and BaseURL elements
- PublishTime now reflects the last change in MPD in ms and not current time.
- availabilityTimeOffset now gives the right PublishTime value for complete segments
- infinite availabilityTimeOffset for SegmentTimeline now results in an error
- Git version and date inserted properly when running "make build"
- livesim2 version header inserted in every HTTP response
- start-over case with
startandstoptime now provides proper dynamic and static MPDs
0.5.1 - 2023-03-09
- make
ato=infwork, i.e. infinite availabilityTimeOffset
- list of complete MPD paths in /assets response
0.5.0 - 2023-03-07
- First public release and version
-
dashfetchertool to fetch a DASH asset online -
livesim2server to stream simulated DASH live - supports SegmentTimeline with
$Time$ - supports SegmentTemplate with
$Number$ - supports low-latency mode with on-the-fly chunking
- features and URLs listed at livesim2 root page
- configurable generated stpp subtitles with timing info