Home Assistant custom integration that normalizes aspect ratio of videos and provides flexible video processing capabilities.
This integration requires the Downloader integration to be installed and configured first. Video Tools uses Downloader's configuration to automatically detect the download directory where videos are processed.
π‘ Tip: Since Video Tools is integrated in Advanced Downloader, consider using Advanced Downloader for a more complete media file management experience, including downloading, resizing, deleting, and more.
-
Install Downloader first (required dependency):
- Go to Settings > Devices & Services
- Click "+ Add Integration"
- Search for "Downloader" and install it
- Configure the download directory
-
Open HACS in your Home Assistant instance
-
Click on "Integrations"
-
Click the three dots in the top right corner and select "Custom repositories"
-
Add the repository URL:
https://github.com/Geek-MD/Video_Normalizer -
Select "Integration" as the category
-
Click "Add"
-
Search for "Video Tools" in HACS
-
Click "Download"
-
Restart Home Assistant
-
Go to Settings > Devices & Services
-
Click the + button to add a new integration
-
Search for "Video Tools"
-
Follow the configuration steps
-
Install Downloader first (required dependency):
- Go to Settings > Devices & Services
- Click "+ Add Integration"
- Search for "Downloader" and install it
- Configure the download directory
-
Copy the
custom_components/video_toolsdirectory to your Home Assistantcustom_componentsdirectory -
Restart Home Assistant
-
Go to Settings > Devices & Services
-
Click the + button to add a new integration
-
Search for "Video Tools"
-
Follow the configuration steps
Note: The setup wizard will automatically detect and use the download directory configured in your Downloader integration.
Note: Video Tools can only be configured once per Home Assistant instance. This ensures proper service and sensor management.
Prerequisite: The Downloader integration must be installed and configured before setting up Video Tools.
During setup, you'll need to configure:
- Download directory: Where videos to be processed are located. This field will be automatically pre-filled from your Downloader integration configuration.
- Processing timeout (optional, default: 300 seconds / 5 minutes): Maximum time to wait for video processing to complete. Optimized for Home Assistant Green hardware specifications (Rockchip RK3566, 4 GB RAM). Increase this value if you frequently process longer or higher-resolution videos.
- Status Sensor - Monitor the integration's processing state with a sensor entity that tracks:
- Current state:
workingoridle - Last job result:
success,skipped, orfailed - Timestamp of last state change (server local time)
- List of processes performed (resize, normalize_aspect, embed_thumbnail, etc.)
- Current state:
- Optional Downloader integration detection and auto-configuration
- Simplified output configuration - specify a single output file path or overwrite the original
- Smart video analysis - automatically detects if video needs processing (aspect ratio, thumbnail, dimensions)
- Automatic aspect ratio normalization for all videos to prevent square or distorted previews in Telegram and mobile players
- Automatic thumbnail generation and embedding to force Telegram to use the correct video preview
- Optional video resizing (width/height) if dimensions differ
- Intelligent skip logic - skips processing if video already meets requirements (unless resize is requested)
- Robust detection of video dimensions using ffprobe (JSON) with ffmpeg -i fallback
- Processing timeout protection - configurable timeout (default: 5 minutes) prevents indefinite hangs on corrupted or extremely large files
- Performance logging - logs elapsed time for all processing operations to help optimize timeout settings
- Emits automation-friendly events on video processing success, failure, or skip
- Easy setup through the Home Assistant UI
Process a video file with normalization operations.
Parameters:
input_file_path(required): Full path to the input video file including filename (e.g., "/media/ring/ring.mp4")output_file_path(optional): Full path for the output video file including filename (e.g., "/media/processed/ring_normalized.mp4"). Only required whenoverwriteis falseoverwrite(optional, default: false): Whether to overwrite the original file. When true,output_file_pathis ignorednormalize_aspect(optional, default: true): Whether to normalize the aspect ratio to 16:9generate_thumbnail(optional, default: true): Whether to generate and embed a thumbnail- resize_width (optional): Target width for resizing (maintains aspect ratio if only one dimension specified)
- resize_height (optional): Target height for resizing (maintains aspect ratio if only one dimension specified)
- target_aspect_ratio (optional, default: 1.777): Target aspect ratio as a decimal (e.g., 1.777 for 16:9, 1.333 for 4:3)
- timeout (optional, default: 300): Maximum time in seconds to wait for processing to complete. If processing takes longer, it will be terminated. Default of 5 minutes is optimized for Home Assistant Green. Increase for longer videos or higher resolutions.
Example automation:
automation:
- alias: "Normalize Downloaded Videos"
trigger:
- platform: event
event_type: folder_watcher
event_data:
event_type: created
condition:
- condition: template
value_template: "{{ trigger.event.data.file.endswith(('.mp4', '.avi', '.mov', '.mkv')) }}"
action:
- service: video_tools.normalize_video
data:
input_file_path: "{{ trigger.event.data.path }}"
output_file_path: "{{ trigger.event.data.path | replace('.mp4', '_normalized.mp4') }}"
normalize_aspect: true
generate_thumbnail: trueThe integration provides a status sensor (sensor.video_tools_status) that tracks the processing state:
-
States:
working: Currently processing a videoidle: Not processing, waiting for work
-
Attributes:
last_job: Result of the last processing job (success,skipped, orfailed)timestamp: ISO 8601 timestamp of when the state last changed (server local time)processes: List of processes performed in the last job (e.g.,["resize", "normalize_aspect", "embed_thumbnail"])
Example automation using the sensor:
automation:
- alias: "Notify when video processing completes"
trigger:
- platform: state
entity_id: sensor.video_tools_status
from: "working"
to: "idle"
action:
- service: notify.mobile_app
data:
title: "Video Processing Complete"
message: >
Result: {{ state_attr('sensor.video_tools_status', 'last_job') }}
Processes: {{ state_attr('sensor.video_tools_status', 'processes') | join(', ') }}The service fires a single event that can be used in automations:
video_tools_video_processing_finished: Fired when video processing completes, regardless of the result. The result is available in the event data under theresultfield, which can besuccess,skipped, orfailed. Additional information about the processing is available in the sensor state attributes.
When the video_tools.normalize_video service is called, it follows a specific lifecycle to ensure proper operation and state management:
- Process Video: The video is processed according to the specified parameters (resize, normalize aspect ratio, generate thumbnail, etc.)
- Fire Event: A Home Assistant event (
video_tools_video_processing_finished) is fired to notify automations of the processing completion. The event includes aresultfield with the valuesuccess,skipped, orfailed - Update Sensor: The status sensor is updated to
idlestate with the appropriate result (success,skipped, orfailed) - Cleanup: Temporary files created during processing are removed
This order ensures that:
- Automations receive events before the sensor state changes, allowing them to react to the event first
- The sensor state accurately reflects when processing is complete before cleanup begins
- Temporary files are cleaned up only after all state updates and notifications are complete
Example of lifecycle in an automation:
automation:
- alias: "Process video and send notification"
trigger:
- platform: event
event_type: video_tools_video_processing_finished
condition:
- condition: template
value_template: "{{ trigger.event.data.result == 'success' }}"
action:
# This action runs immediately after processing, before sensor updates
- service: notify.mobile_app
data:
title: "Video Ready"
message: "Processing complete for {{ trigger.event.data.video_path }}"
- alias: "Handle video processing failures"
trigger:
- platform: event
event_type: video_tools_video_processing_finished
condition:
- condition: template
value_template: "{{ trigger.event.data.result == 'failed' }}"
action:
- service: notify.mobile_app
data:
title: "Video Processing Failed"
message: "Error: {{ trigger.event.data.error }}"
- alias: "Monitor sensor state change"
trigger:
- platform: state
entity_id: sensor.video_tools_status
to: "idle"
action:
# This action runs after the event has been fired
- service: notify.mobile_app
data:
title: "Video Tools Idle"
message: "Status: {{ state_attr('sensor.video_tools_status', 'last_job') }}"This integration requires:
- FFmpeg to be available in the Home Assistant environment (typically pre-installed)
- The Downloader integration (required for auto-detection of the download directory)
π‘ Tip: Since Video Tools is integrated in Advanced Downloader, consider using Advanced Downloader for a more complete media file management experience.
π» Proudly developed with GitHub Copilot π
