{"record":{"id":"cc8018da5a88f596","repo":"remotion-dev/remotion","slug":"only-supporting-non-scrambled-streams","errorCode":null,"errorMessage":"Only supporting non-scrambled streams","messagePattern":"Only supporting non-scrambled streams","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/transport-stream/parse-pes.ts","lineNumber":33,"sourceCode":"\titerator: BufferIterator;\n\toffset: number;\n}) => {\n\tconst ident = iterator.getUint24();\n\tif (ident !== 0x000001) {\n\t\tthrow new Error(`Unexpected PES packet start code: ${ident.toString(16)}`);\n\t}\n\n\tconst streamId = iterator.getUint8();\n\titerator.getUint16(); // PES packet length, is most of the time 0, so useless\n\titerator.startReadingBits();\n\tconst markerBits = iterator.getBits(2);\n\tif (markerBits !== 0b10) {\n\t\tthrow new Error(`Invalid marker bits: ${markerBits}`);\n\t}\n\n\tconst scrambled = iterator.getBits(2);\n\tif (scrambled !== 0b00) {\n\t\tthrow new Error(`Only supporting non-scrambled streams`);\n\t}\n\n\tconst priority = iterator.getBits(1);\n\titerator.getBits(1); // data alignment indicator\n\titerator.getBits(1); // copy right\n\titerator.getBits(1); // original or copy\n\tconst ptsPresent = iterator.getBits(1);\n\tconst dtsPresent = iterator.getBits(1);\n\tif (!ptsPresent && dtsPresent) {\n\t\tthrow new Error(\n\t\t\t`DTS is present but not PTS, this is not allowed in the spec`,\n\t\t);\n\t}\n\n\titerator.getBits(1); // escr flag\n\titerator.getBits(1); // es rate flag\n\titerator.getBits(1); // dsm trick mode flag\n\titerator.getBits(1); // additional copy info flag","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/transport-stream/parse-pes.ts#L15-L51","documentation":"Thrown at parse-pes.ts:33 when the PES_scrambling_control field (2 bits) is anything other than 0b00. Non-zero values mean the PES payload is scrambled (encrypted) with a conditional-access system. The library deliberately does not implement descrambling.","triggerScenarios":"parsePes reads getBits(2) into 'scrambled' and throws if it is not 0b00. Triggered by encrypted broadcast streams (DVB-CSA, ATSC DES), pay-TV captures, or content-protected streams where PES_scrambling_control has been set.","commonSituations":"Recordings from encrypted satellite/cable/IPTV feeds; copy-protected content; streams captured from set-top boxes without descrambling; misconfigured encoders that erroneously set the scrambling bits.","solutions":["Obtain a non-encrypted version of the source stream.","Descramble the stream with an authorized tool (e.g. tsdec for DVB-CSA) before parsing.","If you control the encoder, ensure PES_scrambling_control is left at 00.","Detect encrypted streams upstream and surface a 'content protected' message to users."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Detect scrambled streams upstream\nimport {execSync} from 'node:child_process';\nfunction isScrambled(src: string): boolean {\n  try {\n    const out = execSync(`ffprobe -v error -show_entries stream_flags=scrambled -of json \"${src}\"`).toString();\n    return JSON.parse(out).streams?.some((s: any) => s.flags?.includes('scrambled')) ?? false;\n  } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try { await parseMedia({src}); }\ncatch (e) { if (e instanceof Error && e.message === 'Only supporting non-scrambled streams') { throw new UserError('This stream is encrypted and cannot be parsed.'); } else throw e; }","preventionTips":["Reject encrypted sources before parsing.","Descramble with an authorized tool if you have the rights.","Surface a clear 'encrypted content' error to end users."],"tags":["media-parser","transport-stream","mpegts","pes","drm","encryption"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}