ObjDocumentVideo is a document delegate class for generating thumbnail icons from video files. It extracts a single frame from a video using FFmpeg and converts it into a resized square thumbnail image suitable for preview purposes.
Module: factory.core/ObjDocumentVideo.py
Inherits from: ObjDocumentDelegate.ObjDocumentDelegate
Test file: resource.test/pytests/factory.core/test_ObjDocumentVideo.py
This module enables developers to:
__init__(DB: int = 0) -> NoneInitializes the ObjDocumentVideo instance.
Parameters:
DB (int, optional): Database connection identifier (default: 0)Initialization:
_IsA to "ObjDocumentVideo"extract_thumbnail(file_path: str, output_path: str, seek_time: int = 1) -> boolExtracts a single frame from a video file using ffmpy/FFmpeg.
Parameters:
file_path (str): Path to the input video fileoutput_path (str): Path where the extracted frame will be savedseek_time (int, optional): Time offset in seconds for frame extraction (default: 1)Returns:
True if extraction succeeded and output file existsFalse if extraction failed or exception occurredFFmpeg Options:
-ss {seek_time}: Seek to specified time offset-vframes 1: Extract only one frame-f image2: Force image2 output format-y: Overwrite output file if exists-loglevel quiet: Suppress FFmpeg outputExample:
video = ObjDocumentVideo()
# Extract frame at 1 second (default)
success = video.extract_thumbnail(
"/path/to/video.mp4",
"/tmp/frame.png"
)
# Extract frame at 5 seconds
success = video.extract_thumbnail(
"/path/to/video.mp4",
"/tmp/frame.png",
seek_time=5
)
Error Handling:
# Handles FFmpeg failures gracefully
try:
success = video.extract_thumbnail("video.mp4", "output.png")
if success:
print("Frame extracted successfully")
else:
print("Extraction failed")
except Exception as e:
print(f"Error: {e}")
_do_generate_icon(input_path: str, output_path: str, icon_size: int) -> NoneInternal method that extracts a video frame and converts it to a square thumbnail icon.
Parameters:
input_path (str): Path to the input video fileoutput_path (str): Path where the icon will be savedicon_size (int): Desired size of the square icon in pixelsProcess Flow:
extract_thumbnail() to extract frameDocumentTools.resize_to_square()Error Handling:
Example Usage:
video = ObjDocumentVideo()
# Generate 128x128 thumbnail
video._do_generate_icon(
"/path/to/video.mp4",
"/output/thumbnail.png",
128
)
from ObjDocumentVideo import ObjDocumentVideo
# Create instance
video = ObjDocumentVideo()
# Extract frame and create thumbnail
video._do_generate_icon(
"/videos/sample.mp4",
"/thumbnails/sample_thumb.png",
256
)
from ObjDocumentVideo import ObjDocumentVideo
video = ObjDocumentVideo()
# Extract frame from 10 seconds into the video
success = video.extract_thumbnail(
"/videos/movie.mp4",
"/frames/frame_10s.png",
seek_time=10
)
if success:
print("Frame extracted successfully")
from ObjDocumentVideo import ObjDocumentVideo
import os
video = ObjDocumentVideo()
video_dir = "/videos"
output_dir = "/thumbnails"
for filename in os.listdir(video_dir):
if filename.endswith((".mp4", ".webm", ".mov", ".avi")):
input_path = os.path.join(video_dir, filename)
output_name = os.path.splitext(filename)[0] + ".png"
output_path = os.path.join(output_dir, output_name)
video._do_generate_icon(input_path, output_path, 128)
from ObjDocumentVideo import ObjDocumentVideo
video = ObjDocumentVideo()
try:
success = video.extract_thumbnail(
"/videos/corrupted.mp4",
"/output/frame.png",
seek_time=3
)
if not success:
print("Failed to extract frame - file may be corrupted")
except Exception as e:
print(f"Unexpected error: {e}")
The module has comprehensive test coverage including:
| Test Case | Description | Status |
|---|---|---|
test_isa_set |
Validates _IsA attribute initialization | ✓ |
test_calls_ffmpeg_with_correct_args |
Verifies FFmpeg command construction | ✓ |
test_returns_true_on_success |
Tests successful extraction | ✓ |
test_returns_false_on_failure |
Tests failure handling | ✓ |
test_custom_seek_time |
Tests custom seek time parameter | ✓ |
test_logs_error_on_failure |
Verifies error logging | ✓ |
test_calls_extract_and_resize |
Tests icon generation pipeline | ✓ |
test_logs_when_extract_fails |
Tests logging on extraction failure | ✓ |
test_cleans_up_temp_file |
Verifies temporary file cleanup | ✓ |
test_cleans_up_on_error |
Tests cleanup on exception | ✓ |
Test file location: resource.test/pytests/factory.core/test_ObjDocumentVideo.py
Run tests:
pytest resource.test/pytests/factory.core/test_ObjDocumentVideo.py -v
ffmpy - Python wrapper for FFmpegPIL (Pillow) - Image processing librarytempfile - Temporary file creationObjDocumentDelegate - Base delegate classObjDocumentTools.DocumentTools - Thumbnail resizing utilitiesThis module requires FFmpeg to be installed on the system:
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install ffmpeg
macOS:
brew install ffmpeg
Windows:
Download from https://ffmpeg.org/download.html and add to PATH
ffmpeg -version
from ObjDocumentVideo import ObjDocumentVideo
class VideoDocument:
def __init__(self, video_path):
self.video_path = video_path
self.video_handler = ObjDocumentVideo()
def generate_thumbnail(self, output_dir, size=128):
"""Generate thumbnail for video document."""
filename = os.path.basename(self.video_path)
thumb_name = os.path.splitext(filename)[0] + "_thumb.png"
output_path = os.path.join(output_dir, thumb_name)
self.video_handler._do_generate_icon(
self.video_path,
output_path,
size
)
return output_path
from ObjDocumentVideo import ObjDocumentVideo
video = ObjDocumentVideo()
# Extract frames at different time points
time_points = [1, 5, 10, 15, 20]
for time_point in time_points:
output = f"/frames/frame_{time_point}s.png"
video.extract_thumbnail(
"/videos/sample.mp4",
output,
seek_time=time_point
)
Error: Exception: ffmpeg not found
Solution:
# Verify FFmpeg is installed
which ffmpeg
# If not installed, install it
sudo apt-get install ffmpeg # Ubuntu/Debian
brew install ffmpeg # macOS
Issue: Frame extraction returns True but image is corrupted
Causes:
Solution:
# Test with different seek times
for seek in [0, 1, 2, 5]:
success = video.extract_thumbnail(path, output, seek)
if success and os.path.getsize(output) > 0:
print(f"Valid frame at {seek}s")
break
Error: Permission denied when writing temporary files
Solution:
Ensure write permissions in temp directory:
import tempfile
print(tempfile.gettempdir()) # Check temp directory location
ObjDocumentDelegate.py - Base class for document delegatesObjDocumentTools.py - Shared thumbnail utilitiesObjDocumentAudio.py - Audio file thumbnail generationObjDocument.py - Main document handler that delegates to format-specific handlers