[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7C3KB4V9ME0DVCYVHFBEZJ5":3,"skill-same:01M7C3KB4V9ME0DVCYVHFBEZJ5":45},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":30,"install":31,"resources":44},"01M7C3KB4V9ME0DVCYVHFBEZJ5","video-frame-extraction",null,"Extract frames from video files and save them as images using OpenCV","linyouxue\u002Fskill-repair-benchmark","linyouxue","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F216151464?v=4","01M7BJEVCXKD74KH6FG9CBVSQB","林宥学","01M7BJEVE02NP217V93BKZFC0J",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fevaluation\u002Fresults\u002Fskilltta-synthesis-opus47-tatumass-failed15-20260923\u002Ftasks\u002Fjpg-ocr-stat\u002Frepaired_skill\u002Fvideo-frame-extraction\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: video-frame-extraction\ndescription: Extract frames from video files and save them as images using OpenCV\n---\n\n# Video Frame Extraction Skill\n\n## Purpose\nThis skill enables extraction of individual frames from video files (MP4, AVI, MOV, etc.) using OpenCV. Extracted frames are saved as image files in a specified output directory. It is suitable for video analysis, creating training datasets, thumbnail generation, and preprocessing video content for further processing.\n\n## When to Use\n- Extracting frames for machine learning training data\n- Creating image sequences from video content\n- Generating video thumbnails or preview images\n- Preprocessing videos for object detection or tracking\n- Converting video segments to image collections for analysis\n- Sampling frames at specific intervals for time-lapse effects\n\n## Required Libraries\n\nThe following Python libraries are required:\n\n```python\nimport cv2\nimport os\nimport json\nfrom pathlib import Path\n```\n\n## Input Requirements\n- **File formats**: MP4, AVI, MOV, MKV, WMV, FLV, WEBM\n- **Video codec**: Must be readable by OpenCV (most common codecs supported)\n- **File access**: Read permissions on source video\n- **Output directory**: Write permissions on destination folder\n- **Disk space**: Ensure sufficient space for extracted frames (uncompressed images)\n\n## Output Schema\nAll extraction results must be returned as valid JSON conforming to this schema:\n\n```json\n{\n  \"success\": true,\n  \"source_video\": \"sample.mp4\",\n  \"output_directory\": \"\u002Fpath\u002Fto\u002Fframes\",\n  \"frames_extracted\": 150,\n  \"extraction_params\": {\n    \"interval\": 1,\n    \"start_frame\": 0,\n    \"end_frame\": null,\n    \"output_format\": \"jpg\"\n  },\n  \"video_metadata\": {\n    \"total_frames\": 300,\n    \"fps\": 30.0,\n    \"duration_seconds\": 10.0,\n    \"resolution\": [1920, 1080]\n  },\n  \"output_files\": [\n    \"frame_000001.jpg\",\n    \"frame_000002.jpg\"\n  ],\n  \"warnings\": []\n}\n```\n\n\n### Field Descriptions\n\n- `success`: Boolean indicating whether frame extraction completed\n- `source_video`: Original video filename\n- `output_directory`: Path where frames were saved\n- `frames_extracted`: Total number of frames successfully saved\n- `extraction_params.interval`: Frame sampling interval (1 = every frame, 2 = every other frame, etc.)\n- `extraction_params.start_frame`: First frame index extracted\n- `extraction_params.end_frame`: Last frame index extracted (null if extracted to end)\n- `extraction_params.output_format`: Image format used for saving frames\n- `video_metadata.total_frames`: Total frame count in source video\n- `video_metadata.fps`: Frames per second of source video\n- `video_metadata.duration_seconds`: Video duration in seconds\n- `video_metadata.resolution`: Video dimensions as [width, height]\n- `output_files`: List of generated frame filenames\n- `warnings`: Array of issues encountered during extraction\n\n\n## Code Examples\n\n### Basic Frame Extraction\n\n```python\nimport cv2\nimport os\n\ndef extract_all_frames(video_path, output_dir):\n    \"\"\"Extract all frames from a video file.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    frame_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        filename = os.path.join(output_dir, f\"frame_{frame_count:06d}.jpg\")\n        cv2.imwrite(filename, frame)\n        frame_count += 1\n    \n    cap.release()\n    return frame_count\n```\n\n### Interval-Based Frame Extraction\n\n```python\nimport cv2\nimport os\n\ndef extract_frames_at_interval(video_path, output_dir, interval=1):\n    \"\"\"Extract frames at specified intervals.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    frame_index = 0\n    saved_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        if frame_index % interval == 0:\n            filename = os.path.join(output_dir, f\"frame_{saved_count:06d}.jpg\")\n            cv2.imwrite(filename, frame)\n            saved_count += 1\n        \n        frame_index += 1\n    \n    cap.release()\n    return saved_count\n```\n\n### Full Extraction with JSON Output\n\n```python\nimport cv2\nimport os\nimport json\nfrom pathlib import Path\n\ndef extract_frames_to_json(video_path, output_dir, interval=1, \n                           start_frame=0, end_frame=None, output_format=\"jpg\"):\n    \"\"\"Extract frames and return results as JSON.\"\"\"\n    video_name = os.path.basename(video_path)\n    warnings = []\n    output_files = []\n    \n    try:\n        os.makedirs(output_dir, exist_ok=True)\n        cap = cv2.VideoCapture(video_path)\n        \n        if not cap.isOpened():\n            raise ValueError(f\"Cannot open video: {video_path}\")\n        \n        # Get video metadata\n        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n        fps = cap.get(cv2.CAP_PROP_FPS)\n        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\n        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n        duration = total_frames \u002F fps if fps > 0 else 0\n        \n        # Set end frame if not specified\n        if end_frame is None:\n            end_frame = total_frames\n        \n        # Seek to start frame\n        if start_frame > 0:\n            cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)\n        \n        frame_index = start_frame\n        saved_count = 0\n        \n        while frame_index \u003C end_frame:\n            ret, frame = cap.read()\n            if not ret:\n                if frame_index \u003C end_frame:\n                    warnings.append(f\"Video ended early at frame {frame_index}\")\n                break\n            \n            if (frame_index - start_frame) % interval == 0:\n                filename = f\"frame_{saved_count:06d}.{output_format}\"\n                filepath = os.path.join(output_dir, filename)\n                cv2.imwrite(filepath, frame)\n                output_files.append(filename)\n                saved_count += 1\n            \n            frame_index += 1\n        \n        cap.release()\n        \n        result = {\n            \"success\": True,\n            \"source_video\": video_name,\n            \"output_directory\": str(output_dir),\n            \"frames_extracted\": saved_count,\n            \"extraction_params\": {\n                \"interval\": interval,\n                \"start_frame\": start_frame,\n                \"end_frame\": end_frame,\n                \"output_format\": output_format\n            },\n            \"video_metadata\": {\n                \"total_frames\": total_frames,\n                \"fps\": fps,\n                \"duration_seconds\": round(duration, 2),\n                \"resolution\": [width, height]\n            },\n            \"output_files\": output_files,\n            \"warnings\": warnings\n        }\n        \n    except Exception as e:\n        result = {\n            \"success\": False,\n            \"source_video\": video_name,\n            \"output_directory\": str(output_dir),\n            \"frames_extracted\": 0,\n            \"extraction_params\": {\n                \"interval\": interval,\n                \"start_frame\": start_frame,\n                \"end_frame\": end_frame,\n                \"output_format\": output_format\n            },\n            \"video_metadata\": {\n                \"total_frames\": 0,\n                \"fps\": 0,\n                \"duration_seconds\": 0,\n                \"resolution\": [0, 0]\n            },\n            \"output_files\": [],\n            \"warnings\": [f\"Extraction failed: {str(e)}\"]\n        }\n    \n    return result\n\n# Usage\nresult = extract_frames_to_json(\"video.mp4\", \".\u002Fframes\", interval=10)\nprint(json.dumps(result, indent=2))\n```\n\n### Time-Based Frame Extraction\n\n```python\nimport cv2\nimport os\n\ndef extract_frames_by_seconds(video_path, output_dir, seconds_interval=1.0):\n    \"\"\"Extract frames at specific time intervals (in seconds).\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    fps = cap.get(cv2.CAP_PROP_FPS)\n    frame_interval = int(fps * seconds_interval)\n    \n    if frame_interval \u003C 1:\n        frame_interval = 1\n    \n    frame_index = 0\n    saved_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        if frame_index % frame_interval == 0:\n            filename = os.path.join(output_dir, f\"frame_{saved_count:06d}.jpg\")\n            cv2.imwrite(filename, frame)\n            saved_count += 1\n        \n        frame_index += 1\n    \n    cap.release()\n    return saved_count\n```\n\n### Batch Processing Multiple Videos\n\n```python\nimport cv2\nimport os\nimport json\nfrom pathlib import Path\n\ndef process_video_directory(video_dir, output_base_dir, interval=1):\n    \"\"\"Process all videos in a directory and extract frames.\"\"\"\n    video_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm'}\n    results = []\n    \n    for video_file in sorted(Path(video_dir).iterdir()):\n        if video_file.suffix.lower() in video_extensions:\n            video_output_dir = os.path.join(\n                output_base_dir, \n                video_file.stem\n            )\n            result = extract_frames_to_json(\n                str(video_file), \n                video_output_dir, \n                interval=interval\n            )\n            results.append(result)\n            print(f\"Processed: {video_file.name} -> {result['frames_extracted']} frames\")\n    \n    return results\n```\n\n\n## Extraction Configuration Options\n\n### Output Image Formats\n\n```python\n# JPEG format (default, good balance of quality and size)\ncv2.imwrite(\"frame.jpg\", frame)\n\n# PNG format (lossless, larger files)\ncv2.imwrite(\"frame.png\", frame)\n\n# JPEG with custom quality (0-100)\ncv2.imwrite(\"frame.jpg\", frame, [cv2.IMWRITE_JPEG_QUALITY, 95])\n\n# PNG with compression level (0-9)\ncv2.imwrite(\"frame.png\", frame, [cv2.IMWRITE_PNG_COMPRESSION, 3])\n```\n\n### Frame Seeking Methods\n\n```python\n# Seek by frame number\ncap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)\n\n# Seek by milliseconds\ncap.set(cv2.CAP_PROP_POS_MSEC, milliseconds)\n\n# Seek by ratio (0.0 to 1.0)\ncap.set(cv2.CAP_PROP_POS_AVI_RATIO, 0.5)  # Middle of video\n```\n\n### Frame Resizing\n\n```python\ndef extract_resized_frames(video_path, output_dir, target_size=(640, 480)):\n    \"\"\"Extract and resize frames to specified dimensions.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    frame_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        resized = cv2.resize(frame, target_size)\n        filename = os.path.join(output_dir, f\"frame_{frame_count:06d}.jpg\")\n        cv2.imwrite(filename, resized)\n        frame_count += 1\n    \n    cap.release()\n    return frame_count\n```\n\n\n## Video Metadata Retrieval\n\nExtract video properties before processing:\n\n```python\ndef get_video_info(video_path):\n    \"\"\"Retrieve video metadata.\"\"\"\n    cap = cv2.VideoCapture(video_path)\n    \n    if not cap.isOpened():\n        return None\n    \n    info = {\n        \"total_frames\": int(cap.get(cv2.CAP_PROP_FRAME_COUNT)),\n        \"fps\": cap.get(cv2.CAP_PROP_FPS),\n        \"width\": int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),\n        \"height\": int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),\n        \"codec\": int(cap.get(cv2.CAP_PROP_FOURCC)),\n        \"duration_seconds\": cap.get(cv2.CAP_PROP_FRAME_COUNT) \u002F cap.get(cv2.CAP_PROP_FPS)\n    }\n    \n    cap.release()\n    return info\n```\n\n\n## Specific Frame Extraction\n\nFor extracting frames at exact positions:\n\n```python\ndef extract_specific_frames(video_path, output_dir, frame_numbers):\n    \"\"\"Extract specific frames by their indices.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    extracted = []\n    \n    for frame_num in sorted(frame_numbers):\n        cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)\n        ret, frame = cap.read()\n        \n        if ret:\n            filename = os.path.join(output_dir, f\"frame_{frame_num:06d}.jpg\")\n            cv2.imwrite(filename, frame)\n            extracted.append(frame_num)\n    \n    cap.release()\n    return extracted\n```\n\n\n## Error Handling\n\n### Common Issues and Solutions\n\n**Issue**: Video file cannot be opened\n\n```python\ncap = cv2.VideoCapture(video_path)\nif not cap.isOpened():\n    print(f\"Error: Cannot open video file: {video_path}\")\n    print(\"Check file path, permissions, and codec support\")\n```\n\n**Issue**: Frames read as None\n\n```python\nret, frame = cap.read()\nif not ret or frame is None:\n    print(\"Failed to read frame - video may be corrupted or ended\")\n```\n\n**Issue**: Codec not supported\n\n```python\n# Check if video has valid properties\nfps = cap.get(cv2.CAP_PROP_FPS)\nif fps == 0:\n    print(\"Warning: Could not detect FPS - codec may be unsupported\")\n```\n\n**Issue**: Disk space exhausted\n\n```python\nimport shutil\n\ndef check_disk_space(output_dir, required_mb=100):\n    \"\"\"Check available disk space before extraction.\"\"\"\n    stat = shutil.disk_usage(output_dir)\n    available_mb = stat.free \u002F (1024 * 1024)\n    return available_mb >= required_mb\n```\n\n\n## Quality Self-Check\n\nBefore returning results, verify:\n\n- [ ] Output is valid JSON (use `json.loads()` to validate)\n- [ ] All required fields are present (`success`, `source_video`, `frames_extracted`, `video_metadata`)\n- [ ] Output directory was created successfully\n- [ ] Extracted frame count matches expected value based on interval\n- [ ] Warnings array includes all detected issues\n- [ ] Video was properly released with `cap.release()`\n- [ ] Frame filenames follow consistent zero-padded numbering\n\n\n## Limitations\n\n- OpenCV may not support all video codecs; install additional codecs if needed\n- Seeking in variable frame rate videos may be inaccurate\n- Large videos with high frame counts require significant disk space\n- Memory usage increases with video resolution\n- Some container formats (MKV with certain codecs) may have seeking issues\n- Encrypted or DRM-protected videos cannot be processed\n- Damaged or partially corrupted videos may extract partial results\n\n\n## Version History\n\n- **1.0.0** (2026-01-21): Initial release with OpenCV video frame extraction\n","# Video Frame Extraction Skill\n\n## Purpose\nThis skill enables extraction of individual frames from video files (MP4, AVI, MOV, etc.) using OpenCV. Extracted frames are saved as image files in a specified output directory. It is suitable for video analysis, creating training datasets, thumbnail generation, and preprocessing video content for further processing.\n\n## When to Use\n- Extracting frames for machine learning training data\n- Creating image sequences from video content\n- Generating video thumbnails or preview images\n- Preprocessing videos for object detection or tracking\n- Converting video segments to image collections for analysis\n- Sampling frames at specific intervals for time-lapse effects\n\n## Required Libraries\n\nThe following Python libraries are required:\n\n```python\nimport cv2\nimport os\nimport json\nfrom pathlib import Path\n```\n\n## Input Requirements\n- **File formats**: MP4, AVI, MOV, MKV, WMV, FLV, WEBM\n- **Video codec**: Must be readable by OpenCV (most common codecs supported)\n- **File access**: Read permissions on source video\n- **Output directory**: Write permissions on destination folder\n- **Disk space**: Ensure sufficient space for extracted frames (uncompressed images)\n\n## Output Schema\nAll extraction results must be returned as valid JSON conforming to this schema:\n\n```json\n{\n  \"success\": true,\n  \"source_video\": \"sample.mp4\",\n  \"output_directory\": \"\u002Fpath\u002Fto\u002Fframes\",\n  \"frames_extracted\": 150,\n  \"extraction_params\": {\n    \"interval\": 1,\n    \"start_frame\": 0,\n    \"end_frame\": null,\n    \"output_format\": \"jpg\"\n  },\n  \"video_metadata\": {\n    \"total_frames\": 300,\n    \"fps\": 30.0,\n    \"duration_seconds\": 10.0,\n    \"resolution\": [1920, 1080]\n  },\n  \"output_files\": [\n    \"frame_000001.jpg\",\n    \"frame_000002.jpg\"\n  ],\n  \"warnings\": []\n}\n```\n\n\n### Field Descriptions\n\n- `success`: Boolean indicating whether frame extraction completed\n- `source_video`: Original video filename\n- `output_directory`: Path where frames were saved\n- `frames_extracted`: Total number of frames successfully saved\n- `extraction_params.interval`: Frame sampling interval (1 = every frame, 2 = every other frame, etc.)\n- `extraction_params.start_frame`: First frame index extracted\n- `extraction_params.end_frame`: Last frame index extracted (null if extracted to end)\n- `extraction_params.output_format`: Image format used for saving frames\n- `video_metadata.total_frames`: Total frame count in source video\n- `video_metadata.fps`: Frames per second of source video\n- `video_metadata.duration_seconds`: Video duration in seconds\n- `video_metadata.resolution`: Video dimensions as [width, height]\n- `output_files`: List of generated frame filenames\n- `warnings`: Array of issues encountered during extraction\n\n\n## Code Examples\n\n### Basic Frame Extraction\n\n```python\nimport cv2\nimport os\n\ndef extract_all_frames(video_path, output_dir):\n    \"\"\"Extract all frames from a video file.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    frame_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        filename = os.path.join(output_dir, f\"frame_{frame_count:06d}.jpg\")\n        cv2.imwrite(filename, frame)\n        frame_count += 1\n    \n    cap.release()\n    return frame_count\n```\n\n### Interval-Based Frame Extraction\n\n```python\nimport cv2\nimport os\n\ndef extract_frames_at_interval(video_path, output_dir, interval=1):\n    \"\"\"Extract frames at specified intervals.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    frame_index = 0\n    saved_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        if frame_index % interval == 0:\n            filename = os.path.join(output_dir, f\"frame_{saved_count:06d}.jpg\")\n            cv2.imwrite(filename, frame)\n            saved_count += 1\n        \n        frame_index += 1\n    \n    cap.release()\n    return saved_count\n```\n\n### Full Extraction with JSON Output\n\n```python\nimport cv2\nimport os\nimport json\nfrom pathlib import Path\n\ndef extract_frames_to_json(video_path, output_dir, interval=1, \n                           start_frame=0, end_frame=None, output_format=\"jpg\"):\n    \"\"\"Extract frames and return results as JSON.\"\"\"\n    video_name = os.path.basename(video_path)\n    warnings = []\n    output_files = []\n    \n    try:\n        os.makedirs(output_dir, exist_ok=True)\n        cap = cv2.VideoCapture(video_path)\n        \n        if not cap.isOpened():\n            raise ValueError(f\"Cannot open video: {video_path}\")\n        \n        # Get video metadata\n        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n        fps = cap.get(cv2.CAP_PROP_FPS)\n        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\n        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n        duration = total_frames \u002F fps if fps > 0 else 0\n        \n        # Set end frame if not specified\n        if end_frame is None:\n            end_frame = total_frames\n        \n        # Seek to start frame\n        if start_frame > 0:\n            cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)\n        \n        frame_index = start_frame\n        saved_count = 0\n        \n        while frame_index \u003C end_frame:\n            ret, frame = cap.read()\n            if not ret:\n                if frame_index \u003C end_frame:\n                    warnings.append(f\"Video ended early at frame {frame_index}\")\n                break\n            \n            if (frame_index - start_frame) % interval == 0:\n                filename = f\"frame_{saved_count:06d}.{output_format}\"\n                filepath = os.path.join(output_dir, filename)\n                cv2.imwrite(filepath, frame)\n                output_files.append(filename)\n                saved_count += 1\n            \n            frame_index += 1\n        \n        cap.release()\n        \n        result = {\n            \"success\": True,\n            \"source_video\": video_name,\n            \"output_directory\": str(output_dir),\n            \"frames_extracted\": saved_count,\n            \"extraction_params\": {\n                \"interval\": interval,\n                \"start_frame\": start_frame,\n                \"end_frame\": end_frame,\n                \"output_format\": output_format\n            },\n            \"video_metadata\": {\n                \"total_frames\": total_frames,\n                \"fps\": fps,\n                \"duration_seconds\": round(duration, 2),\n                \"resolution\": [width, height]\n            },\n            \"output_files\": output_files,\n            \"warnings\": warnings\n        }\n        \n    except Exception as e:\n        result = {\n            \"success\": False,\n            \"source_video\": video_name,\n            \"output_directory\": str(output_dir),\n            \"frames_extracted\": 0,\n            \"extraction_params\": {\n                \"interval\": interval,\n                \"start_frame\": start_frame,\n                \"end_frame\": end_frame,\n                \"output_format\": output_format\n            },\n            \"video_metadata\": {\n                \"total_frames\": 0,\n                \"fps\": 0,\n                \"duration_seconds\": 0,\n                \"resolution\": [0, 0]\n            },\n            \"output_files\": [],\n            \"warnings\": [f\"Extraction failed: {str(e)}\"]\n        }\n    \n    return result\n\n# Usage\nresult = extract_frames_to_json(\"video.mp4\", \".\u002Fframes\", interval=10)\nprint(json.dumps(result, indent=2))\n```\n\n### Time-Based Frame Extraction\n\n```python\nimport cv2\nimport os\n\ndef extract_frames_by_seconds(video_path, output_dir, seconds_interval=1.0):\n    \"\"\"Extract frames at specific time intervals (in seconds).\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    fps = cap.get(cv2.CAP_PROP_FPS)\n    frame_interval = int(fps * seconds_interval)\n    \n    if frame_interval \u003C 1:\n        frame_interval = 1\n    \n    frame_index = 0\n    saved_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        if frame_index % frame_interval == 0:\n            filename = os.path.join(output_dir, f\"frame_{saved_count:06d}.jpg\")\n            cv2.imwrite(filename, frame)\n            saved_count += 1\n        \n        frame_index += 1\n    \n    cap.release()\n    return saved_count\n```\n\n### Batch Processing Multiple Videos\n\n```python\nimport cv2\nimport os\nimport json\nfrom pathlib import Path\n\ndef process_video_directory(video_dir, output_base_dir, interval=1):\n    \"\"\"Process all videos in a directory and extract frames.\"\"\"\n    video_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm'}\n    results = []\n    \n    for video_file in sorted(Path(video_dir).iterdir()):\n        if video_file.suffix.lower() in video_extensions:\n            video_output_dir = os.path.join(\n                output_base_dir, \n                video_file.stem\n            )\n            result = extract_frames_to_json(\n                str(video_file), \n                video_output_dir, \n                interval=interval\n            )\n            results.append(result)\n            print(f\"Processed: {video_file.name} -> {result['frames_extracted']} frames\")\n    \n    return results\n```\n\n\n## Extraction Configuration Options\n\n### Output Image Formats\n\n```python\n# JPEG format (default, good balance of quality and size)\ncv2.imwrite(\"frame.jpg\", frame)\n\n# PNG format (lossless, larger files)\ncv2.imwrite(\"frame.png\", frame)\n\n# JPEG with custom quality (0-100)\ncv2.imwrite(\"frame.jpg\", frame, [cv2.IMWRITE_JPEG_QUALITY, 95])\n\n# PNG with compression level (0-9)\ncv2.imwrite(\"frame.png\", frame, [cv2.IMWRITE_PNG_COMPRESSION, 3])\n```\n\n### Frame Seeking Methods\n\n```python\n# Seek by frame number\ncap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)\n\n# Seek by milliseconds\ncap.set(cv2.CAP_PROP_POS_MSEC, milliseconds)\n\n# Seek by ratio (0.0 to 1.0)\ncap.set(cv2.CAP_PROP_POS_AVI_RATIO, 0.5)  # Middle of video\n```\n\n### Frame Resizing\n\n```python\ndef extract_resized_frames(video_path, output_dir, target_size=(640, 480)):\n    \"\"\"Extract and resize frames to specified dimensions.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    frame_count = 0\n    \n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        resized = cv2.resize(frame, target_size)\n        filename = os.path.join(output_dir, f\"frame_{frame_count:06d}.jpg\")\n        cv2.imwrite(filename, resized)\n        frame_count += 1\n    \n    cap.release()\n    return frame_count\n```\n\n\n## Video Metadata Retrieval\n\nExtract video properties before processing:\n\n```python\ndef get_video_info(video_path):\n    \"\"\"Retrieve video metadata.\"\"\"\n    cap = cv2.VideoCapture(video_path)\n    \n    if not cap.isOpened():\n        return None\n    \n    info = {\n        \"total_frames\": int(cap.get(cv2.CAP_PROP_FRAME_COUNT)),\n        \"fps\": cap.get(cv2.CAP_PROP_FPS),\n        \"width\": int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),\n        \"height\": int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),\n        \"codec\": int(cap.get(cv2.CAP_PROP_FOURCC)),\n        \"duration_seconds\": cap.get(cv2.CAP_PROP_FRAME_COUNT) \u002F cap.get(cv2.CAP_PROP_FPS)\n    }\n    \n    cap.release()\n    return info\n```\n\n\n## Specific Frame Extraction\n\nFor extracting frames at exact positions:\n\n```python\ndef extract_specific_frames(video_path, output_dir, frame_numbers):\n    \"\"\"Extract specific frames by their indices.\"\"\"\n    os.makedirs(output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    extracted = []\n    \n    for frame_num in sorted(frame_numbers):\n        cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)\n        ret, frame = cap.read()\n        \n        if ret:\n            filename = os.path.join(output_dir, f\"frame_{frame_num:06d}.jpg\")\n            cv2.imwrite(filename, frame)\n            extracted.append(frame_num)\n    \n    cap.release()\n    return extracted\n```\n\n\n## Error Handling\n\n### Common Issues and Solutions\n\n**Issue**: Video file cannot be opened\n\n```python\ncap = cv2.VideoCapture(video_path)\nif not cap.isOpened():\n    print(f\"Error: Cannot open video file: {video_path}\")\n    print(\"Check file path, permissions, and codec support\")\n```\n\n**Issue**: Frames read as None\n\n```python\nret, frame = cap.read()\nif not ret or frame is None:\n    print(\"Failed to read frame - video may be corrupted or ended\")\n```\n\n**Issue**: Codec not supported\n\n```python\n# Check if video has valid properties\nfps = cap.get(cv2.CAP_PROP_FPS)\nif fps == 0:\n    print(\"Warning: Could not detect FPS - codec may be unsupported\")\n```\n\n**Issue**: Disk space exhausted\n\n```python\nimport shutil\n\ndef check_disk_space(output_dir, required_mb=100):\n    \"\"\"Check available disk space before extraction.\"\"\"\n    stat = shutil.disk_usage(output_dir)\n    available_mb = stat.free \u002F (1024 * 1024)\n    return available_mb >= required_mb\n```\n\n\n## Quality Self-Check\n\nBefore returning results, verify:\n\n- [ ] Output is valid JSON (use `json.loads()` to validate)\n- [ ] All required fields are present (`success`, `source_video`, `frames_extracted`, `video_metadata`)\n- [ ] Output directory was created successfully\n- [ ] Extracted frame count matches expected value based on interval\n- [ ] Warnings array includes all detected issues\n- [ ] Video was properly released with `cap.release()`\n- [ ] Frame filenames follow consistent zero-padded numbering\n\n\n## Limitations\n\n- OpenCV may not support all video codecs; install additional codecs if needed\n- Seeking in variable frame rate videos may be inaccurate\n- Large videos with high frame counts require significant disk space\n- Memory usage increases with video resolution\n- Some container formats (MKV with certain codecs) may have seeking issues\n- Encrypted or DRM-protected videos cannot be processed\n- Damaged or partially corrupted videos may extract partial results\n\n\n## Version History\n\n- **1.0.0** (2026-01-21): Initial release with OpenCV video frame extraction\n",{"name":5,"description":7},"main","cdcb6d230f3b15c3c33f8a2bdd16439f43602cbe","evaluation\u002Fresults\u002Fskilltta-synthesis-opus47-tatumass-failed15-20260923\u002Ftasks\u002Fjpg-ocr-stat\u002Frepaired_skill\u002Fvideo-frame-extraction",1,"https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark","https:\u002F\u002Fgithub.com\u002Flinyouxue","2026-11-14 20:28:35",{"source":8,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add linyouxue\u002Fskill-repair-benchmark --skill video-frame-extraction",{"tool":37,"command":38},"bunx","bunx skills add linyouxue\u002Fskill-repair-benchmark --skill video-frame-extraction",{"tool":40,"command":41},"pnpm","pnpm dlx skills add linyouxue\u002Fskill-repair-benchmark --skill video-frame-extraction","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fevaluation\u002Fresults\u002Fskilltta-synthesis-opus47-tatumass-failed15-20260923\u002Ftasks\u002Fjpg-ocr-stat\u002Frepaired_skill\u002Fvideo-frame-extraction\u002FSKILL.md",true,[],[46,51,58,65,70,75],{"skillNo":47,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":48,"categories":49,"keywords":50,"publishedAt":19},"01M7E1HGVRY73NBJ022CJG13X6","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fvideo-frame-extraction\u002FSKILL.md",[],[],{"skillNo":52,"name":53,"nameZh":6,"description":54,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":55,"categories":56,"keywords":57,"publishedAt":19},"01M7E1HAG5R7CJ9C8NYJS771MB","openai-vision","Analyze images and multi-frame sequences using OpenAI GPT vision models","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fopenai-vision\u002FSKILL.md",[],[],{"skillNo":59,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":62,"categories":63,"keywords":64,"publishedAt":19},"01M7E1H7DADKB6QBWKC2KQ63SZ","image-ocr","Extract text content from images using Tesseract OCR via Python, including structured field extraction from receipts and forms","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fimage-ocr\u002FSKILL.md",[],[],{"skillNo":66,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":69,"publishedAt":19},"01M7E1H0WBNT43TENGQY7AVZHD","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fvideo-frame-extraction\u002FSKILL.md",[],[],{"skillNo":71,"name":53,"nameZh":6,"description":54,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":19},"01M7E1GTC7D4N4Q2EF03875J9E","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fopenai-vision\u002FSKILL.md",[],[],{"skillNo":76,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":19},"01M7E1GQ92CWFMGH53KSSE4WER","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fimage-ocr\u002FSKILL.md",[],[]]