VideoHelp Forum




+ Reply to Thread
Results 1 to 6 of 6
  1. Posting this because the symptoms look like three unrelated bugs, the error messages point nowhere useful, and I could not find a correct explanation anywhere. It took a while to track down.

    Symptoms

    The file plays perfectly in VLC, MPC-HC, PotPlayer, Windows Media Player. Then:
    • ffprobe / ffplay reports a multi-gigabyte video as Input #0, png_pipe — a 1x1 image, no duration
    • NVDEC / PyNvVideoCodec: cuvidCreateVideoParser(...) returned error 300
    • OpenCV: Could not find decoder for codec_id=61, then a missing-duration crash

    Three toolchains, three unrelated-looking errors, one cause. Nobody searching for one of them ever finds the others, which is most of why this stays unexplained.

    What is in the file

    The video is intact — nothing corrupt, nothing missing. There is a small image glued to the front:

    Code:
    [ 70-byte PNG ][ ...valid MPEG-TS stream... ]
      ^ byte 0       ^ real video starts here
    The PNG is a 1x1 fully transparent pixel. It renders as nothing at all. Not a broken thumbnail — no visual purpose whatsoever. That is the shape of a tracking beacon: something meant to be requested, not seen.

    Some CDNs attach this to every segment response. Concatenating the segments, which is what every HLS downloader does, puts one copy at byte 0. I counted the PNG signatures across a 3.4 GB affected file and got 1188 — one per segment. The other 1187 are harmless: an MPEG-TS demuxer resynchronizes on the next sync byte and skips straight over them. Only the copy at offset 0 breaks anything.

    Sizes vary. Current samples are 70 bytes with no padding; files from early 2025 use about 120 bytes plus 85 bytes of 0xFF filler, so the payload starts at 205 rather than 70. Do not hardcode an offset.

    Why the split behavior

    Tolerant players scan forward looking for something they recognise, find the stream, and play it without ever mentioning the prefix. Strict parsers trust byte 0: ffprobe matches the PNG signature and reports an image, NVDEC gets bytes that are not a video stream, OpenCV asks for a PNG decoder (codec_id=61 is AV_CODEC_ID_PNG) and falls over.

    Fixing it

    Not a re-encode. The video was never damaged — you locate where the real stream begins, copy from there to EOF, and rewrap. Runs at disk speed, no quality loss.

    By hand, once you know the offset:

    Code:
    ffmpeg -fflags +genpts -i input.ts -map 0:v:0 -map 0:a:0 -c copy -movflags +faststart output.mp4
    ...but you still have to strip the prefix first, and the offset varies per file.

    I wrote a tool that does the whole thing: CleanStreamTS (Windows, MIT, single installer, GUI and CLI). Point it at a folder; it queues anything repairable automatically and writes clean copies alongside. Originals are never modified.

    Verified rather than assumed — on a 1.3 GB file the video bitstream MD5 is identical before and after, with matching frame counts (119742 video / 187288 audio) and the same duration to the microsecond. The only structural change is moving the container index to the front, which also makes the result seek instantly instead of reading to EOF first.

    It will not guess

    MPEG-TS packets start with 0x47 every 188 bytes, but a single 0x47 occurs roughly once per 256 bytes of arbitrary data — it proves nothing on its own. The tool only accepts a payload when the sync byte recurs at eight consecutive 188-byte-aligned positions. A decoy prefix over something unrecognised is reported and left alone, because writing a file from a guessed offset would turn a recoverable file into a broken one.

    Two things worth separating

    Removing the prefix fixes the parser failures. It does not give you a file an HTML5 <video> element can play — browsers cannot play raw MPEG-TS regardless, so anything with a browser-based preview still needs the MP4 remux above. Those are independent problems and I spent a while conflating them.

    Prevention

    The cleaner path is not writing the prefix in the first place. liveDownload strips it from each segment at download time, so its output needs no repair. Validated rather than assumed: the same title downloaded raw with the strip active and repaired offline with CleanStreamTS both process end-to-end in lada with identical frame counts (119742), and the raw stripped file also passes a full NVDEC-based pipeline with zero decode errors. Other downloaders write exactly what the server sent — which is the whole problem.

    Reporting variants

    The tool's scan output masks filenames by default (first ten characters plus a short hash) so it can be pasted publicly. If you get one reported as decoy_prefixed_unknown_payload, that is a variant I have not seen — the scan line and, if you can capture it, the .m3u8 manifest would be useful.


    Posting this because the symptoms look like three unrelated bugs, the error messages point nowhere useful, and I could not find a correct explanation anywhere. It took a while to track down.
    Image Attached Thumbnails Click image for larger version

Name:	CleanStream-Cleaning.png
Views:	25
Size:	66.2 KB
ID:	93581  

    Click image for larger version

Name:	liveDownload.png
Views:	16
Size:	175.8 KB
ID:	93582  

    Last edited by gsadasivan; 27th Aug 2026 at 20:32.
    Quote Quote  
  2. Can you show some manifests where the media segments show this issue? Does it only concern HLS manifests, or also DASH mpds?

    I have not understood why media publishers or CDNs would be doing this. They can use CMAF fragmented MP4 segments to share the same segments between HLS and DASH streams. If they still need to use MPEG-TS for old clients, I don't understand the point of the prefixed image data.
    Quote Quote  
  3. This is all probably AI.
    Quote Quote  
  4. I haven't encountered this issue in developing dash-mpd-cli, perhaps because this isn't used for DASH streaming, but I'm curious and can't find any information on the motivation for this online. If anyone can share a public manifest or example media segments on a CDN I'd be interested.
    Quote Quote  
  5. @larley — thanks for that link, genuinely. It is the best public evidence in this thread. For anyone who does not read C#: that file is N_m3u8DL-RE's segment handler for exactly this phenomenon. It detects four image types glued to the front of media segments (PNG, GIF, BMP, JPEG), and for PNG it carries four hardcoded decoy sizes — 69, 120, 771 and 6102 bytes — with a fallback that scans for the 0x47 TS sync byte recurring at 188-byte intervals when none of the known sizes match. My samples (70 bytes current, ~120 + 85 bytes of 0xFF padding from early 2025) sit right in that family, and the padded variant is why scanning beats fixed offsets: slice a known size off the front and the padding still lands at byte 0.

    So yes — common enough that the most-used m3u8 downloader ships a workaround with a list of known decoys in it. What I could not find anywhere is a written explanation of the failure signature — why the same file plays in VLC, reports as a 1x1 image in ffprobe, kills NVDEC with error 300 and OpenCV with codec_id=61. Three toolchains, three vocabularies, no cross-reference. That gap is what this thread is for, and it being searchable is the point.

    @pteque — good questions, in order:

    HLS only, or DASH too? Everything I have observed is HLS with MPEG-TS segments, and I think there is a structural reason it stays there. The trick is only free where players tolerate it: a TS demuxer (and hls.js's transmuxer) resynchronises on the next 0x47 and skips the junk, so real playback never breaks. Fragmented MP4 has no resync — a parser walks box lengths from byte 0, so a prefixed image would break the site's own players via MSE. A publisher doing this on DASH/CMAF would DoS themselves. Your not encountering it in dash-mpd-cli is consistent with that, not a gap in your testing. You are right that CMAF would let a legitimate publisher unify HLS/DASH — but the operators doing this are not standards-minded publishers; they are grey-market streaming hosts where TS is entrenched, and TS's resync tolerance is precisely what makes the trick invisible.

    Why do it at all? I cannot prove intent, so here are the two explanations that fit the bytes, for whatever they are worth. (1) Content-type camouflage: the response carries genuine image magic bytes, so anything that sniffs content — CDN rules, traffic classifiers, corporate proxies, hosting terms that treat video differently from images — sees an image. Video riding image-classified paths is an old trick and this is a cheap way to survive magic-byte checks. (2) Scraper-breaking that costs players nothing: naive tooling that feeds segments or concatenated output to strict parsers falls over, while every real player scans past it. I will note honestly that my opening post leaned on the "tracking pixel" framing; having since established the image rides on every segment response rather than being fetched separately, camouflage fits better than tracking — nothing extra is ever requested. I have updated my view; the repair is identical either way.

    Can I share a manifest? Not usefully as links: the URLs are tokenised with ~24h validity, and the hosts serve adult content, which I am not going to link here. What I can give you is everything needed to reproduce the failure signature without any site involved. The current 70-byte decoy, byte-exact:

    Code:
    89504e470d0a1a0a0000000d49484452000000010000000108060000
    001f15c4890000000d49444154789c6360606060000000050001a5f6
    45400000000049454e44ae426082
    That is a complete, valid PNG: 1x1, RGBA, fully transparent, minimal chunk set (IHDR + IDAT + IEND). Reproduce the whole phenomenon in three commands:

    Code:
    python -c "open('decoy.png','wb').write(bytes.fromhex('89504e470d0a1a0a0000000d49484452000000010000000108060000001f15c4890000000d49444154789c6360606060000000050001a5f645400000000049454e44ae426082'))"
    ffmpeg -f lavfi -i testsrc=duration=5:size=320x240:rate=25 -c:v libx264 -f mpegts seg.ts
    python -c "open('poisoned.ts','wb').write(open('decoy.png','rb').read()+open('seg.ts','rb').read())"
    Then:
    Code:
    ffprobe poisoned.ts
    reports png_pipe, 1x1 — a five-second test video the size of a movie, identified as a single pixel. VLC plays it fine. That is the entire bug in miniature.

    The manifests themselves are unremarkable, which is part of what took so long to see: a plain media playlist, ~400 #EXTINF entries of ~10s each, no EXT-X-MAP, every segment URI on one CDN host. Nothing in the manifest hints at anything — the prefix is applied to the segment responses, which is why counting PNG signatures across a finished 3.4 GB file returns 1188, one per segment. Since the tokens expire quickly, if you like, I can PM you a link that a user sent me, upon request.
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!