{"record":{"id":"0159eada119a10ce","repo":"deepfakes/faceswap","slug":"there-is-a-mismatch-between-the-number-of-frames-f","errorCode":null,"errorMessage":"There is a mismatch between the number of frames found in the video file ({len(pts_time)}) and the number of frames found in the alignments file ({len(self.data)}).\\nThis can be caused by a number of issues:\\n  - The video has a Variable Frame Rate and FFMPEG is having a hard time calculating the correct number of frames.\\n  - You are working with a Merged Alignments file. This is not supported for your current use case.\\nYou should either extract the video to individual frames, re-encode the video at a constant frame rate and re-run extraction or work with a dedicated alignments file for your requested video.","messagePattern":"There is a mismatch between the number of frames found in the video file \\(\\{len\\(pts_time\\)\\}\\) and the number of frames found in the alignments file \\(\\{len\\(self\\.data\\)\\}\\)\\.\\\\nThis can be caused by a number of issues:\\\\n  - The video has a Variable Frame Rate and FFMPEG is having a hard time calculating the correct number of frames\\.\\\\n  - You are working with a Merged Alignments file\\. This is not supported for your current use case\\.\\\\nYou should either extract the video to individual frames, re-encode the video at a constant frame rate and re-run extraction or work with a dedicated alignments file for your requested video\\.","errorType":"exception","errorClass":"FaceswapError","httpStatus":null,"severity":"critical","filePath":"lib/align/alignments.py","lineNumber":198,"sourceCode":"        sample_filename = next(fname for fname in self.data)\n        basename = sample_filename[:sample_filename.rfind(\"_\")]\n        ext = os.path.splitext(sample_filename)[-1]\n        logger.debug(\"sample filename: '%s', base filename: '%s' extension: '%s'\",\n                     sample_filename, basename, ext)\n        logger.info(\"Saving video meta information to Alignments file\")\n\n        for idx, pts in enumerate(pts_time):\n            meta:  dict[T.Literal[\"pts_time\", \"keyframe\"], int] = {\"pts_time\": pts,\n                                                                   \"keyframe\": idx in keyframes}\n            key = f\"{basename}_{idx + 1:06d}{ext}\"\n            if key not in self.data:\n                self.data[key] = AlignmentsEntry(video_meta=meta)\n            else:\n                self.data[key].video_meta = meta\n\n        logger.debug(\"Alignments count: %s, timestamp count: %s\", len(self.data), len(pts_time))\n        if len(self.data) != len(pts_time):\n            raise FaceswapError(\n                \"There is a mismatch between the number of frames found in the video file \"\n                f\"({len(pts_time)}) and the number of frames found in the alignments file \"\n                f\"({len(self.data)}).\\nThis can be caused by a number of issues:\"\n                \"\\n  - The video has a Variable Frame Rate and FFMPEG is having a hard time \"\n                \"calculating the correct number of frames.\"\n                \"\\n  - You are working with a Merged Alignments file. This is not supported for \"\n                \"your current use case.\"\n                \"\\nYou should either extract the video to individual frames, re-encode the \"\n                \"video at a constant frame rate and re-run extraction or work with a dedicated \"\n                \"alignments file for your requested video.\")\n        self._io.save()\n\n    # << VALIDATION >> #\n    def frame_exists(self, frame_name: str) -> bool:\n        \"\"\"Check whether a given frame_name exists within the alignments :attr:`data`.\n\n        Parameters\n        ----------","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/deepfakes/faceswap/blob/f530cb7508ae670f6474f8a7d9c4df94705cf96b/lib/align/alignments.py#L180-L216","documentation":"Raised by Alignments.save_timecodes/update flow (lib/align/alignments.py) after merging video frame timestamps (pts_time from FFProbe) into the alignments data: the number of keys in the alignments file must equal the number of frames FFProbe found in the video. A mismatch means the alignments were generated against a different frame set than the current video.","triggerScenarios":"Calling the alignments tool job that writes video metadata (e.g. 'extract'/'sort' video-meta update) on a Variable Frame Rate video where FFProbe miscounts frames, or supplying an alignments file that covers more than one video (merged alignments) or was built from extracted frames then reused against a re-encoded video.","commonSituations":"Processing a screen recording or phone-captured VFR video; using one combined alignments file across multiple clips; re-encoding a video (changing frame count) after extraction; ffmpeg/ffprobe version differences in frame counting.","solutions":["Extract the video to individual PNG frames and run the job against the frames folder instead of the video file","Re-encode the video at a constant frame rate (e.g. ffmpeg -i in.mp4 -vsync cfr -r <fps> out.mp4) and re-run extraction","Use a dedicated alignments file for this video rather than a merged alignments file (check with the alignments tool that frame counts match)"],"exampleFix":"# before: VFR video used directly\nfaceswap.py align -a alignments.fsa -v input.mov  # -> frame count mismatch\n\n# after: re-encode CFR first\nffmpeg -i input.mov -vsync cfr -r 30 -pix_fmt yuv420p input_cfr.mp4\nfaceswap.py align -a alignments_cfr.fsa -v input_cfr.mp4","handlingStrategy":"validation","validationCode":"import subprocess, json\n\ndef ffprobe_frame_count(video):\n    out = subprocess.check_output([\n        \"ffprobe\", \"-v\", \"error\", \"-select_streams\", \"v:0\",\n        \"-count_packets\", \"-show_entries\", \"stream=nb_read_packets\",\n        \"-of\", \"json\", video])\n    return json.loads(out)[\"streams\"][0][\"nb_read_packets\"]\n\n# compare against len(alignments.frames) before running the video-meta job","typeGuard":null,"tryCatchPattern":"try:\n    alignments.save_timecodes(...)\nexcept FaceswapError as err:\n    if \"mismatch between the number of frames\" in str(err):\n        # fall back to frames-based workflow\n        extract_to_frames(video)\n    else:\n        raise","preventionTips":["Prefer extracted image sequences over raw video for alignment jobs","Normalize videos to CFR before extraction (ffmpeg -vsync cfr)","Keep one alignments file per video; never merge across clips"],"tags":["faceswap","alignments","video","vfr","ffprobe"],"backgroundTag":null,"analyzedSha":"f530cb7508ae670f6474f8a7d9c4df94705cf96b","analyzedAt":"2026-08-15T02:59:26.626Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}