{"record":{"id":"f06c38e3b0556450","repo":"remotion-dev/remotion","slug":"the-provided-matrix-is-not-a-valid-rotation-matrix","errorCode":null,"errorMessage":"The provided matrix is not a valid rotation matrix.","messagePattern":"The provided matrix is not a valid rotation matrix\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/media-parser/src/containers/iso-base-media/tkhd.ts","lineNumber":35,"sourceCode":"\twidth: number;\n\theight: number;\n\tunrotatedWidth: number;\n\tunrotatedHeight: number;\n\trotation: number;\n}\n\ntype Matrix2x2 = readonly [number, number, number, number];\n\nfunction getRotationAngleFromMatrix(matrix: Matrix2x2): number {\n\t// Extract elements from the matrix\n\tconst [a, b, c, d] = matrix;\n\tif (a === 0 && b === 0 && c === 0 && d === 0) {\n\t\treturn 0;\n\t}\n\n\t// Check if the matrix is a valid rotation matrix\n\tif (Math.round(a * a + b * b) !== 1 || Math.round(c * c + d * d) !== 1) {\n\t\tthrow new Error('The provided matrix is not a valid rotation matrix.');\n\t}\n\n\t// Calculate the angle using the atan2 function\n\tconst angleRadians = Math.atan2(c, a); // atan2(sin(θ), cos(θ))\n\tconst angleDegrees = angleRadians * (180 / Math.PI); // Convert radians to degrees\n\n\treturn angleDegrees;\n}\n\nconst applyRotation = ({\n\tmatrix,\n\twidth,\n\theight,\n}: {\n\tmatrix: Matrix2x2;\n\twidth: number;\n\theight: number;\n}) => {","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/tkhd.ts#L17-L53","documentation":"The TKHD (Track Header) parser extracts a 2x2 sub-matrix from the 3x3 transformation matrix to derive a rotation angle. It validates that the rows are unit length (a*a+b*b ≈ 1 and c*c+d*d ≈ 1); if not, the matrix is not a pure rotation and the throw fires. The earlier all-zero guard returns 0 (no rotation), so this throw only hits when the matrix has non-zero but non-orthogonal values.","triggerScenarios":"A tkhd matrix whose upper-left 2x2 block is non-zero but not a valid rotation (rows not unit length). This can happen with files that embed a skew, scale, or perspective matrix instead of a pure rotation, or with corrupted matrix bytes.","commonSituations":"Files from non-standard encoders that write scale or shear transforms into the tkhd matrix; corrupt tkhd data; or files with intentionally identity-but-not-unit matrices. The round() tolerance means small floating-point drift is tolerated, so genuine corruption is the usual cause.","solutions":["Inspect the tkhd matrix with `mp4dump input.mp4 | grep -A12 tkhd`.","Re-mux: `ffmpeg -i input.mp4 -c copy -movflags +faststart remuxed.mp4` to normalize the matrix to identity or a clean rotation.","Apply rotation via ffmpeg metadata if rotation metadata is needed: `ffmpeg -i input.mp4 -c copy -metadata:s:v:0 rotate=0 out.mp4`.","Transcode to regenerate tkhd: `ffmpeg -i input.mp4 -c:v libx264 out.mp4`."],"exampleFix":"// before: tkhd has skew/scale matrix that fails unit-length check\nffmpeg -i input.mp4 -c copy -movflags +faststart remuxed.mp4\n// after: tkhd matrix is identity or clean rotation","handlingStrategy":"try-catch","validationCode":"// Validate the tkhd 2x2 sub-matrix is a valid rotation before parsing\nfunction isValidRotationMatrix(a: number, b: number, c: number, d: number): boolean {\n  if (a === 0 && b === 0 && c === 0 && d === 0) return true;\n  return Math.round(a*a + b*b) === 1 && Math.round(c*c + d*d) === 1;\n}","typeGuard":"type Matrix2x2 = readonly [number, number, number, number];\nfunction isValidRotationMatrix(m: Matrix2x2): boolean {\n  const [a, b, c, d] = m;\n  if (a === 0 && b === 0 && c === 0 && d === 0) return true;\n  return Math.round(a*a + b*b) === 1 && Math.round(c*c + d*d) === 1;\n}","tryCatchPattern":"try {\n  await parseMedia({src, fields: {dimensions: true}});\n} catch (err) {\n  if (err instanceof Error && err.message.includes('not a valid rotation matrix')) {\n    // tkhd has skew/scale matrix; re-mux to normalize or transcode\n  } else throw err;\n}","preventionTips":["Re-mux with ffmpeg to reset the tkhd matrix to identity.","Avoid producing files with non-rotation transforms in tkhd.","Use ffprobe -show_streams to inspect rotation metadata before parsing."],"tags":["media-parser","isobmff","tkhd-box","rotation-matrix","corrupt-file","mp4"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}