Skip to content

Commit 5206487

Browse files
committed
Add utility function for video compression
1 parent 1183abe commit 5206487

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

ethology/io/video_utils.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,92 @@ def get_video_specs(video_path: str):
9090
"duration": float(data.get("format", {}).get("duration", 0)),
9191
"streams": streams,
9292
}
93+
94+
95+
def compress_video(
96+
input_path: str,
97+
output_path: str,
98+
crf: int = 23,
99+
preset: str = "superfast",
100+
overwrite: bool = True,
101+
):
102+
"""Compress video using H.264 codec with specified quality settings.
103+
104+
Parameters
105+
----------
106+
input_path : str
107+
Path to the input video file.
108+
109+
output_path : str
110+
Path where the compressed video file will be saved.
111+
112+
crf : int, optional
113+
Constant Rate Factor determining the quality and bitrate.
114+
Lower values yield higher quality and larger file sizes
115+
(range 0-51, typical 18-28).
116+
Default is 23.
117+
118+
preset : str, optional
119+
The encoding speed preset. Faster presets result in larger files
120+
but quicker encoding. Options include 'ultrafast', 'superfast',
121+
'veryfast', 'faster', 'fast', 'medium', 'slow', 'slower',
122+
'veryslow'.
123+
Default is 'superfast'.
124+
125+
overwrite : bool, optional
126+
If True, overwrite the output file if it already exists.
127+
Default is True.
128+
129+
Returns
130+
-------
131+
bool
132+
True if successful, False if an error occurred
133+
134+
Raises
135+
------
136+
FileNotFoundError if the video file does not exist.
137+
138+
Example:
139+
--------
140+
>>> from ethology.io.video_utils import compress_video
141+
>>> compress_video("input.mp4", "output.mp4")
142+
True
143+
>>> compress_video("input.mp4", "output.mp4", crf=20, preset="medium")
144+
True
145+
146+
"""
147+
path = Path(input_path)
148+
if not path.exists():
149+
raise FileNotFoundError(f"Video file not found: {input_path}")
150+
151+
cmd = [
152+
"ffmpeg",
153+
"-y" if overwrite else "",
154+
"-i",
155+
str(input_path),
156+
"-c:v",
157+
"libx264",
158+
"-pix_fmt",
159+
"yuv420p",
160+
"-preset",
161+
preset,
162+
"-crf",
163+
str(crf),
164+
"-progress",
165+
"pipe:1",
166+
str(output_path),
167+
]
168+
169+
cmd = [
170+
arg for arg in cmd if arg
171+
] # Filter out empty args, say in case of overwrite=False
172+
173+
try:
174+
subprocess.run(cmd, capture_output=True, text=True, check=True)
175+
print("File compressed successfully!")
176+
return True
177+
178+
except subprocess.CalledProcessError as e:
179+
print(f"FFmpeg error: {e.stderr}")
180+
print("File compression failed.")
181+
return False

0 commit comments

Comments
 (0)