smartcut

repository·main·Indexed 43 days ago

https://github.com/skeskinen/smartcut

An open-source CLI tool for efficient video cutting that minimizes recoding by only processing video around cutpoints. Version 1.7 supports precise cutting using timestamps or frame numbers via --keep and --cut options, preserving original quality for the rest of the file. It includes a MediaContainer class for analyzing GOP structures, keyframe locations, and stream details across various formats including MP4, MKV, AVI, and MOV.

Tokens
8.1K
Snippets
32
Records
38
Agent score
53%

What's inside smartcut

  1. Run smartcut tests

    main

    The project includes a test suite for various video and audio formats. You can run specific subsets of tests using the smartcut_tests.py script with the --category flag.

    # Test synthetic H.264 tests only
    python smartcut_tests.py --category h264
    
    # Test only real-world H.264 videos
    python smartcut_tests.py --category real_world_h264
    
    # Test all real-world videos (all codecs)
    python smartcut_tests.py --category real_world
    
    # See all available categories
    python smartcut_tests.py --list-categories
    python smartcut_tests.py --category h264
  2. Use smartcut to keep or cut video segments

    main

    The smartcut CLI requires an input file path and an output file path as positional arguments. You can define which parts of the video to preserve or remove using the --keep (or -k) and --cut (or -c) options.

    Keep segments

    Use --keep to specify the time ranges you want to retain. The tool will discard everything else.

    smartcut input.mp4 output.mp4 --keep 10,20,40,50

    This example keeps the segment from 10s to 20s and the segment from 40s to 50s.

    Cut segments

    Use --cut to specify the time ranges you want to remove. The tool will keep everything except these segments.

    smartcut input.mp4 output.mp4 --cut 30,40,01:00,01:10

    This example removes the segment from 30s to 40s and the segment from 1m to 1m10s.

    Shorthands and Keywords

    • Shorthands: -k for --keep, -c for --cut.
    • Start/End Keywords: Use start (or s) and end (or e) to define boundaries.
      • smartcut input.mp4 output.mp4 -k start,30,01:00,end (Keeps from start to 30s, and from 1m to end).
    • Negative Timestamps: Use negative values to count backwards from the end of the file.
      • smartcut input.mp4 output.mp4 -c "-5,end" (Cuts the last 5 seconds).
      • smartcut input.mp4 output.mp4 -k 10,-10 (Keeps from 10s to 10s before the end).
      • smartcut input.mp4 output.mp4 -k 0,-1:30 (Keeps everything except the last 1m30s).
  3. Install smartcut from source

    main

    To install from the source repository, clone the repository, set up a Python virtual environment, and install the package locally.

    # Clone this repository:
    git clone https://github.com/skeskinen/smartcut.git
    cd smartcut
    
    # Create python virtual environment:
    python -m venv venv
    source venv/bin/activate
    
    # Install the project to venv along with required dependencies:
    pip install .
    
    # Run:
    python ./smartcut input.mp4 output.mp4 --keep 10,20,40,50
    git clone https://github.com/skeskinen/smartcut.git
    cd smartcut
    python -m venv venv
    source venv/bin/activate
    pip install .
    python ./smartcut input.mp4 output.mp4 --keep 10,20,40,50
  4. How Smartcut and Recode modes work

    main

    Smartcut works by attempting to preserve the original codec and bitstream. It uses av.bitstream.BitStreamFilterContext (e.g., h264_mp4toannexb) to ensure packets are compatible with the new container.

    Recode mode is used when VideoExportMode.RECODE is selected or a codec_override is provided. In this mode, VideoCutter initializes an encoder, decodes frames from the source, and re-encodes them using the specified quality settings (CRF).

  5. Understand GOP and NAL type analysis in MediaContainer

    main

    For video containers (specifically H.264 and H.265), MediaContainer performs deep analysis of the GOP structure to ensure safe cutting. It tracks:

    • gop_start_times_dts: DTS (Decoding Time Stamp) of the start of each GOP.
    • gop_end_times_dts: DTS of the end of each GOP.
    • gop_start_nal_types: The NAL unit type of the first picture frame after a GOP boundary.
    • gop_leading_end_dts: The DTS of the first non-leading picture in a GOP (useful for identifying CRA/leading picture sequences).
    • gop_has_rasl: Boolean indicating if a GOP contains RASL (Random Access Leading Slice) frames, which may require specific priming or hybrid recoding.
  6. How frame-based cutting works

    main

    By passing the --frames flag, the values provided to --keep or --cut are treated as zero-indexed frame numbers rather than timestamps.

    Special case: Using -1 as a frame number refers to the final frame of the video.

    Example:

    smartcut input.mp4 output.mp4 --keep 300,600,1200,1500 --frames
  7. Configure VideoExportMode and VideoSettings

    main

    To control how video is processed during a cut, use the VideoSettings dataclass. You must specify a VideoExportMode (e.g., RECODE or copy) and a VideoExportQuality. If you are in RECODE mode, you can provide a codec_override string to specify a particular codec (e.g., 'libx264'), otherwise it defaults to 'copy'.

    from smartcut.media_utils import VideoExportMode, VideoExportQuality
    from smartcut.video_cutter import VideoSettings
    
    # Example: Full recode with high quality
    settings = VideoSettings(
        mode=VideoExportMode.RECODE,
        quality=VideoExportQuality.HIGH,
        codec_override='libx265'
    )
    
    # Example: Smartcut (copy) mode
    copy_settings = VideoSettings(
        mode=VideoExportMode.copy,
        quality=VideoExportQuality.LOSSLESS
    )
  8. Reference: smartcut CLI options

    main

    The following options are available for the smartcut command line interface:

    OptionShorthandDescription
    --keep-kSpecify segments to keep (comma-separated time ranges)
    --cut-cSpecify segments to cut (comma-separated time ranges)
    --log-levelN/ASet the logging verbosity (e.g., info)

    Positional Arguments:

    1. input: Path to the source video file.
    2. output: Path to the destination video file.
  9. Get Default Codecs for a Container

    main

    Use these functions to find the recommended default codec for a given file extension:

    • get_default_audio_codec_for_container(container_ext)
    • get_default_video_codec_for_container(container_ext)

    Default Mappings:

    • mp4: Audio AAC, Video H264
    • webm: Audio LIBOPUS, Video VP9
    • mp3: Audio MP3 (audio-only)
    • wav: Audio PCM_S16LE (audio-only)
    from smartcut.media_utils import get_default_video_codec_for_container
    
    default_video = get_default_video_codec_for_container('mp4')
    # Returns VideoCodec.H264
  10. Snap to frame times with MediaContainer

    main

    The MediaContainer provides methods to find the nearest frame timestamps, which is useful for precise cutting or seeking. These methods work for video files using video frame times, or audio-only files using the first audio track's frame times.

    • get_next_frame_time(t: Fraction) -> Fraction: Returns the closest frame time to the given time t (relative to start_time=0).
    • get_frame_time_at_or_before(t: Fraction) -> Fraction: Snaps down to the frame time at or immediately before t.
    • get_frame_time_at_or_after(t: Fraction) -> Fraction: Snaps up to the frame time at or immediately after t.
    from fractions import Fraction
    
    # Snap to the frame at or before 5.5 seconds
    frame_time = container.get_frame_time_at_or_before(Fraction(5, 1) + Fraction(1, 2))
    
    # Snap to the frame at or after 10.2 seconds
    next_frame = container.get_frame_time_at_or_after(Fraction(102, 10))