How video-use Handles Portrait Source Detection and Scaling: A Technical Deep Dive
video-use detects portrait videos by checking if height exceeds width using ffprobe, then applies height-based scaling filters (scale=-2:1280 or scale=-2:1920) for vertical videos and width-based scaling for landscape videos during the ffmpeg rendering pipeline.
The video-use repository provides automated video processing utilities that handle orientation-aware transcoding. Understanding how the library manages portrait source detection and scaling is crucial for developers working with mixed-orientation video content. The implementation relies on ffprobe for dimension analysis and dynamically constructs ffmpeg filter chains based on orientation flags.
Detecting Portrait Orientation with ffprobe
The orientation detection logic centers on dimension comparison using ffprobe metadata.
The is_portrait_source() Function
In helpers/render.py, the is_portrait_source() function (lines 34-46) executes ffprobe to retrieve video dimensions and returns True when the video's height exceeds its width:
# Conceptual implementation based on helpers/render.py#L34-L46
def is_portrait_source(video_path):
# Uses ffprobe to get width and height
height > width # Returns True for portrait orientation
This boolean flag drives all subsequent scaling decisions in the rendering pipeline.
Scaling Logic for Portrait vs Landscape Videos
Once orientation is determined, the extract_segment() function (lines 73-78 in helpers/render.py) selects appropriate scaling filters based on the portrait flag and rendering mode.
Draft Preview Scaling (1280px)
For draft previews, video-use applies dimension-specific scaling to balance quality and processing speed:
- Portrait videos: Use
scale=-2:1280(height 1280px, width auto-calculated) - Landscape videos: Use
scale=1280:-2(width 1280px, height auto-calculated)
The -2 value ensures ffmpeg calculates the missing dimension while maintaining the original aspect ratio and keeping the value divisible by 2 for codec compatibility.
Final Render Scaling (1920px)
For final renders and high-quality outputs, the pipeline switches to 1920px maximum dimensions:
- Portrait videos: Use
scale=-2:1920(height 1920px) - Landscape videos: Use
scale=1920:-2(width 1920px)
This approach ensures that vertical videos maintain their portrait orientation while fitting within standard 1080p workflows.
Implementation in the Rendering Pipeline
The scaling logic integrates directly into ffmpeg's video filter chain. After extract_segment() determines the appropriate scale string, it concatenates this value with other filters (such as HDR tonemapping or color grading) to form the final -vf argument.
The complete pipeline follows this sequence:
- Detection:
is_portrait_source()queries ffprobe for dimensions - Decision:
extract_segment()selects height-based or width-based scaling - Execution: The scale filter joins the ffmpeg command's video filter chain
Code Examples and Usage
Basic Rendering Commands
The script automatically detects portrait sources without manual intervention:
# Standard render – automatically detects and scales portrait sources
python helpers/render.py edl.json -o final.mp4
# Draft preview – applies 1280px scaling limits
python helpers/render.py edl.json -o preview.mp4 --draft
Debug Portrait Detection
Verify orientation detection for specific files:
python -c "
from pathlib import Path
from helpers.render import is_portrait_source
print(is_portrait_source(Path('path/to/video.mp4')))
"
Generated ffmpeg Commands
When video-use processes a portrait source, the generated ffmpeg command includes height-based scaling:
# Portrait video output
ffmpeg -i input.mp4 -vf "scale=-2:1920,format=yuv420p" output.mp4
For landscape sources, the command switches to width-based scaling:
# Landscape video output
ffmpeg -i input.mp4 -vf "scale=1920:-2,format=yuv420p" output.mp4
Summary
- video-use determines orientation by comparing height and width using ffprobe in
is_portrait_source()(lines 34-46 ofhelpers/render.py). - Portrait videos (height > width) receive height-based scaling filters (
scale=-2:1280for drafts,scale=-2:1920for final renders). - Landscape videos receive width-based scaling filters (
scale=1280:-2orscale=1920:-2). - The
extract_segment()function (lines 73-78) applies these filters dynamically based on the draft flag and orientation. - The chosen scale parameter integrates into ffmpeg's
-vfvideo filter chain alongside other processing filters.
Frequently Asked Questions
How does video-use determine if a video is portrait or landscape?
The is_portrait_source() function in helpers/render.py executes ffprobe to retrieve the video's width and height metadata. It returns True when the height value exceeds the width, indicating a portrait (vertical) orientation rather than landscape.
What is the difference between draft and final render scaling?
Draft previews use 1280px as the maximum dimension (scale=-2:1280 for portrait, scale=1280:-2 for landscape), while final renders use 1920px (scale=-2:1920 or scale=1920:-2). This allows draft processing to complete faster with lower resolution outputs while maintaining the correct aspect ratio.
Why does the scaling filter use -2 instead of -1?
The -2 value in ffmpeg's scale filter ensures that the automatically calculated dimension is divisible by 2, which is required for most video codecs (including H.264). Using -1 could result in odd-numbered dimensions that cause encoding errors or compatibility issues.
Can I override the automatic portrait detection?
The current implementation in helpers/render.py automatically detects orientation using is_portrait_source() within the extract_segment() function. To force a specific orientation, you would need to modify the source code to bypass the ffprobe check or manually set the portrait flag before the scaling logic executes at lines 73-78.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →