ffmpeg-python-helper 2.0.0__tar.gz → 3.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ffmpeg_python_helper-2.0.0/README.md → ffmpeg_python_helper-3.1.0/PKG-INFO +26 -5
- ffmpeg_python_helper-2.0.0/PKG-INFO → ffmpeg_python_helper-3.1.0/README.md +17 -14
- {ffmpeg_python_helper-2.0.0 → ffmpeg_python_helper-3.1.0}/pyproject.toml +2 -2
- {ffmpeg_python_helper-2.0.0 → ffmpeg_python_helper-3.1.0}/pyproject.toml.orig +2 -2
- {ffmpeg_python_helper-2.0.0 → ffmpeg_python_helper-3.1.0}/src/ffmpeg_python_helper/__init__.py +19 -3
- {ffmpeg_python_helper-2.0.0 → ffmpeg_python_helper-3.1.0}/src/ffmpeg_python_helper/ffmpeg_api.py +185 -39
- ffmpeg_python_helper-3.1.0/src/ffmpeg_python_helper/pipe_helper.py +114 -0
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ffmpeg-python-helper
|
|
3
|
+
Version: 3.1.0
|
|
4
|
+
Summary: A Python wrapper for FFMPEG that provides a simple, intuitive API for common video processing tasks including format conversion, GIF creation, and video trimming.
|
|
5
|
+
Author: marjon
|
|
6
|
+
Author-email: marjon <petmalu.marjon@gmail.com>
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
1
10
|
# FFMPEG Python Helper
|
|
2
11
|
|
|
3
12
|
A Python wrapper for FFMPEG that provides a simple, intuitive API for common video processing tasks.
|
|
@@ -7,7 +16,8 @@ A Python wrapper for FFMPEG that provides a simple, intuitive API for common vid
|
|
|
7
16
|
- 🔧 **Easy FFMPEG Integration** - Automatically detects FFMPEG installation
|
|
8
17
|
- 🎥 **Video Processing** - Reformat videos between formats
|
|
9
18
|
- 🎞️ **GIF Creation** - Convert videos to optimized GIFs with customizable settings
|
|
10
|
-
-
|
|
19
|
+
- 🎵 **Audio Extraction** - Extract audio tracks from videos without re-encoding
|
|
20
|
+
- 🧠 **In-Memory Processing** - Process video/audio data directly from bytes without temporary files
|
|
11
21
|
- ✂️ **Video Trimming** - Trim videos with precise start time and duration control
|
|
12
22
|
- 🐍 **Pythonic API** - Clean, object-oriented interface with proper error handling
|
|
13
23
|
- 📁 **File Validation** - Automatic input file existence checking
|
|
@@ -48,12 +58,13 @@ output = ffmpeg.reformat("input.mp4", "output.avi")
|
|
|
48
58
|
print(output.decode())
|
|
49
59
|
|
|
50
60
|
# Create a GIF from video
|
|
51
|
-
|
|
52
|
-
print(output.decode())
|
|
61
|
+
ffmpeg.gif("video.mp4", "animation.gif", fps=15, scale=480)
|
|
53
62
|
|
|
54
63
|
# Trim a video
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
ffmpeg.trim("video.mp4", "short_clip.mp4", start=10.5, duration=5.0)
|
|
65
|
+
|
|
66
|
+
# Extract audio from video
|
|
67
|
+
ffmpeg.extract_audio("video.mp4", "audio.m4a")
|
|
57
68
|
|
|
58
69
|
# Create GIF from in-memory video data
|
|
59
70
|
with open("video.mp4", "rb") as f:
|
|
@@ -61,6 +72,16 @@ with open("video.mp4", "rb") as f:
|
|
|
61
72
|
gif_data = ffmpeg.gifs(video_data, fps=15, scale=480)
|
|
62
73
|
with open("memory.gif", "wb") as f:
|
|
63
74
|
f.write(gif_data)
|
|
75
|
+
|
|
76
|
+
# Trim video in memory
|
|
77
|
+
trimmed_data = ffmpeg.trims(video_data, start=0, duration=30)
|
|
78
|
+
with open("trimmed.mp4", "wb") as f:
|
|
79
|
+
f.write(trimmed_data)
|
|
80
|
+
|
|
81
|
+
# Extract audio in memory
|
|
82
|
+
audio_data = ffmpeg.extract_audios(video_data, output_format="m4a")
|
|
83
|
+
with open("audio.m4a", "wb") as f:
|
|
84
|
+
f.write(audio_data)
|
|
64
85
|
```
|
|
65
86
|
|
|
66
87
|
## API Reference
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: ffmpeg-python-helper
|
|
3
|
-
Version: 2.0.0
|
|
4
|
-
Summary: A Python wrapper for FFMPEG that provides a simple, intuitive API for common video processing tasks including format conversion, GIF creation, and video trimming.
|
|
5
|
-
Author: marjon
|
|
6
|
-
Author-email: marjon <marjongodito@gmanmi.com>
|
|
7
|
-
Requires-Python: >=3.14
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
|
|
10
1
|
# FFMPEG Python Helper
|
|
11
2
|
|
|
12
3
|
A Python wrapper for FFMPEG that provides a simple, intuitive API for common video processing tasks.
|
|
@@ -16,7 +7,8 @@ A Python wrapper for FFMPEG that provides a simple, intuitive API for common vid
|
|
|
16
7
|
- 🔧 **Easy FFMPEG Integration** - Automatically detects FFMPEG installation
|
|
17
8
|
- 🎥 **Video Processing** - Reformat videos between formats
|
|
18
9
|
- 🎞️ **GIF Creation** - Convert videos to optimized GIFs with customizable settings
|
|
19
|
-
-
|
|
10
|
+
- 🎵 **Audio Extraction** - Extract audio tracks from videos without re-encoding
|
|
11
|
+
- 🧠 **In-Memory Processing** - Process video/audio data directly from bytes without temporary files
|
|
20
12
|
- ✂️ **Video Trimming** - Trim videos with precise start time and duration control
|
|
21
13
|
- 🐍 **Pythonic API** - Clean, object-oriented interface with proper error handling
|
|
22
14
|
- 📁 **File Validation** - Automatic input file existence checking
|
|
@@ -57,12 +49,13 @@ output = ffmpeg.reformat("input.mp4", "output.avi")
|
|
|
57
49
|
print(output.decode())
|
|
58
50
|
|
|
59
51
|
# Create a GIF from video
|
|
60
|
-
|
|
61
|
-
print(output.decode())
|
|
52
|
+
ffmpeg.gif("video.mp4", "animation.gif", fps=15, scale=480)
|
|
62
53
|
|
|
63
54
|
# Trim a video
|
|
64
|
-
|
|
65
|
-
|
|
55
|
+
ffmpeg.trim("video.mp4", "short_clip.mp4", start=10.5, duration=5.0)
|
|
56
|
+
|
|
57
|
+
# Extract audio from video
|
|
58
|
+
ffmpeg.extract_audio("video.mp4", "audio.m4a")
|
|
66
59
|
|
|
67
60
|
# Create GIF from in-memory video data
|
|
68
61
|
with open("video.mp4", "rb") as f:
|
|
@@ -70,6 +63,16 @@ with open("video.mp4", "rb") as f:
|
|
|
70
63
|
gif_data = ffmpeg.gifs(video_data, fps=15, scale=480)
|
|
71
64
|
with open("memory.gif", "wb") as f:
|
|
72
65
|
f.write(gif_data)
|
|
66
|
+
|
|
67
|
+
# Trim video in memory
|
|
68
|
+
trimmed_data = ffmpeg.trims(video_data, start=0, duration=30)
|
|
69
|
+
with open("trimmed.mp4", "wb") as f:
|
|
70
|
+
f.write(trimmed_data)
|
|
71
|
+
|
|
72
|
+
# Extract audio in memory
|
|
73
|
+
audio_data = ffmpeg.extract_audios(video_data, output_format="m4a")
|
|
74
|
+
with open("audio.m4a", "wb") as f:
|
|
75
|
+
f.write(audio_data)
|
|
73
76
|
```
|
|
74
77
|
|
|
75
78
|
## API Reference
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ffmpeg-python-helper"
|
|
3
|
-
version = "
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "A Python wrapper for FFMPEG that provides a simple, intuitive API for common video processing tasks including format conversion, GIF creation, and video trimming."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.14"
|
|
@@ -8,7 +8,7 @@ dependencies = []
|
|
|
8
8
|
|
|
9
9
|
[[project.authors]]
|
|
10
10
|
name = "marjon"
|
|
11
|
-
email = "
|
|
11
|
+
email = "petmalu.marjon@gmail.com"
|
|
12
12
|
|
|
13
13
|
[project.scripts]
|
|
14
14
|
ffmpeg-python-helper = "ffmpeg_python_helper:main"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ffmpeg-python-helper"
|
|
3
|
-
version = "
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "A Python wrapper for FFMPEG that provides a simple, intuitive API for common video processing tasks including format conversion, GIF creation, and video trimming."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
7
|
-
{ name = "marjon", email = "
|
|
7
|
+
{ name = "marjon", email = "petmalu.marjon@gmail.com" }
|
|
8
8
|
]
|
|
9
9
|
requires-python = ">=3.14"
|
|
10
10
|
dependencies = []
|
{ffmpeg_python_helper-2.0.0 → ffmpeg_python_helper-3.1.0}/src/ffmpeg_python_helper/__init__.py
RENAMED
|
@@ -2,29 +2,45 @@
|
|
|
2
2
|
FFMPEG Python Helper - A Python wrapper for FFMPEG video processing.
|
|
3
3
|
|
|
4
4
|
This package provides a simple, intuitive API for common video processing tasks
|
|
5
|
-
including format conversion, GIF creation, video trimming,
|
|
5
|
+
including format conversion, GIF creation, video trimming, audio extraction,
|
|
6
|
+
in-memory processing, and data pipeline utilities.
|
|
6
7
|
|
|
7
8
|
Example:
|
|
8
|
-
>>> from ffmpeg_python_helper import FFMPEG
|
|
9
|
+
>>> from ffmpeg_python_helper import FFMPEG, Pipe
|
|
9
10
|
>>> ffmpeg = FFMPEG()
|
|
10
11
|
>>> ffmpeg.reformat("input.mp4", "output.avi")
|
|
11
12
|
>>> ffmpeg.gif("video.mp4", "animation.gif", fps=15, scale=480)
|
|
12
13
|
>>> ffmpeg.trim("video.mp4", "short_clip.mp4", start=10.5, duration=5.0)
|
|
14
|
+
>>> ffmpeg.extract_audio("video.mp4", "audio.m4a")
|
|
13
15
|
>>>
|
|
14
16
|
>>> # In-memory processing
|
|
15
17
|
>>> with open("video.mp4", "rb") as f:
|
|
16
18
|
... video_data = f.read()
|
|
17
19
|
>>> gif_data = ffmpeg.gifs(video_data, fps=15, scale=480)
|
|
20
|
+
>>> trimmed_data = ffmpeg.trims(video_data, start=0, duration=30)
|
|
21
|
+
>>> audio_data = ffmpeg.extract_audios(video_data, output_format="m4a")
|
|
22
|
+
>>>
|
|
23
|
+
>>> # Pipeline processing
|
|
24
|
+
>>> def process_video(data: bytes) -> bytes:
|
|
25
|
+
... return ffmpeg.trims(data, start=0, duration=30)
|
|
26
|
+
>>>
|
|
27
|
+
>>> def convert_to_gif(data: bytes) -> bytes:
|
|
28
|
+
... return ffmpeg.gifs(data, fps=15, scale=480)
|
|
29
|
+
>>>
|
|
30
|
+
>>> processed_data = Pipe.pipe_bytes(video_data, process_video, convert_to_gif)
|
|
18
31
|
|
|
19
32
|
For detailed API documentation, see:
|
|
20
33
|
- FFMPEG class documentation
|
|
34
|
+
- Pipe class documentation
|
|
21
35
|
- README.md for usage examples and tutorials
|
|
22
36
|
"""
|
|
23
37
|
|
|
24
38
|
from .ffmpeg_api import FFMPEG
|
|
39
|
+
from .pipe_helper import Pipe
|
|
25
40
|
|
|
26
41
|
__all__ = [
|
|
27
|
-
'FFMPEG'
|
|
42
|
+
'FFMPEG',
|
|
43
|
+
'Pipe'
|
|
28
44
|
]
|
|
29
45
|
|
|
30
46
|
__version__ = "0.1.0"
|
{ffmpeg_python_helper-2.0.0 → ffmpeg_python_helper-3.1.0}/src/ffmpeg_python_helper/ffmpeg_api.py
RENAMED
|
@@ -8,8 +8,9 @@ class FFMPEG:
|
|
|
8
8
|
common video processing tasks.
|
|
9
9
|
|
|
10
10
|
This class automatically detects FFMPEG installation in the system PATH
|
|
11
|
-
and provides methods for video conversion, GIF creation,
|
|
12
|
-
It supports both file-based operations and
|
|
11
|
+
and provides methods for video conversion, GIF creation, video trimming,
|
|
12
|
+
and audio extraction. It supports both file-based operations and
|
|
13
|
+
in-memory data processing.
|
|
13
14
|
|
|
14
15
|
Example:
|
|
15
16
|
>>> from ffmpeg_python_helper import FFMPEG
|
|
@@ -17,11 +18,14 @@ class FFMPEG:
|
|
|
17
18
|
>>> ffmpeg.reformat("input.mp4", "output.avi")
|
|
18
19
|
>>> ffmpeg.gif("video.mp4", "animation.gif", fps=15, scale=480)
|
|
19
20
|
>>> ffmpeg.trim("video.mp4", "short_clip.mp4", start=10.5, duration=5.0)
|
|
21
|
+
>>> ffmpeg.extract_audio("video.mp4", "audio.m4a")
|
|
20
22
|
>>>
|
|
21
23
|
>>> # In-memory processing
|
|
22
24
|
>>> with open("video.mp4", "rb") as f:
|
|
23
25
|
... video_data = f.read()
|
|
24
26
|
>>> gif_data = ffmpeg.gifs(video_data, fps=15, scale=480)
|
|
27
|
+
>>> trimmed_data = ffmpeg.trims(video_data, start=0, duration=30)
|
|
28
|
+
>>> audio_data = ffmpeg.extract_audios(video_data, output_format="m4a")
|
|
25
29
|
|
|
26
30
|
Attributes:
|
|
27
31
|
executable (str): The path to the FFMPEG executable found in the system PATH.
|
|
@@ -165,7 +169,7 @@ in your system PATH.
|
|
|
165
169
|
return stderr
|
|
166
170
|
|
|
167
171
|
def gifs(self,
|
|
168
|
-
|
|
172
|
+
input_bytes: bytes,
|
|
169
173
|
fps: int = 10,
|
|
170
174
|
scale: int = 320) -> bytes:
|
|
171
175
|
"""
|
|
@@ -217,7 +221,7 @@ in your system PATH.
|
|
|
217
221
|
"-vf", filter_graph,
|
|
218
222
|
"-f", "gif",
|
|
219
223
|
"pipe:1",
|
|
220
|
-
input_data=
|
|
224
|
+
input_data=input_bytes
|
|
221
225
|
)
|
|
222
226
|
|
|
223
227
|
return stdout
|
|
@@ -227,7 +231,7 @@ in your system PATH.
|
|
|
227
231
|
output_file: str,
|
|
228
232
|
fps: int = 10,
|
|
229
233
|
scale: int = 320
|
|
230
|
-
) ->
|
|
234
|
+
) -> None:
|
|
231
235
|
"""
|
|
232
236
|
Convert a video file to an optimized GIF.
|
|
233
237
|
|
|
@@ -241,27 +245,21 @@ in your system PATH.
|
|
|
241
245
|
scale: Width of the GIF in pixels. Height is auto-scaled
|
|
242
246
|
to maintain aspect ratio. Defaults to 320.
|
|
243
247
|
|
|
244
|
-
Returns:
|
|
245
|
-
bytes: FFMPEG output (stdout or stderr) as bytes.
|
|
246
|
-
|
|
247
248
|
Raises:
|
|
248
249
|
FileNotFoundError: If input file doesn't exist.
|
|
249
250
|
RuntimeError: If GIF file was not created successfully.
|
|
250
251
|
|
|
251
252
|
Example:
|
|
252
253
|
>>> # Create a standard GIF
|
|
253
|
-
>>>
|
|
254
|
-
>>> print(output.decode())
|
|
254
|
+
>>> ffmpeg.gif("video.mp4", "output.gif")
|
|
255
255
|
|
|
256
256
|
>>> # Create a higher quality GIF with custom settings
|
|
257
|
-
>>>
|
|
258
|
-
...
|
|
259
|
-
>>> print(output.decode())
|
|
257
|
+
>>> ffmpeg.gif("video.mp4", "output.gif",
|
|
258
|
+
... fps=15, scale=640)
|
|
260
259
|
|
|
261
260
|
>>> # Create a small thumbnail GIF
|
|
262
|
-
>>>
|
|
263
|
-
...
|
|
264
|
-
>>> print(output.decode())
|
|
261
|
+
>>> ffmpeg.gif("video.mp4", "thumbnail.gif",
|
|
262
|
+
... fps=5, scale=160)
|
|
265
263
|
"""
|
|
266
264
|
input_path = Path(input_file)
|
|
267
265
|
output_path = Path(output_file)
|
|
@@ -279,7 +277,7 @@ in your system PATH.
|
|
|
279
277
|
"[s1][p]paletteuse"
|
|
280
278
|
)
|
|
281
279
|
|
|
282
|
-
|
|
280
|
+
self.execute(
|
|
283
281
|
"-y",
|
|
284
282
|
"-i", str(input_path),
|
|
285
283
|
"-vf", filter_graph,
|
|
@@ -291,18 +289,13 @@ in your system PATH.
|
|
|
291
289
|
f"GIF was not created: {output_file}"
|
|
292
290
|
)
|
|
293
291
|
|
|
294
|
-
if stderr:
|
|
295
|
-
return stderr
|
|
296
|
-
|
|
297
|
-
return stdout
|
|
298
|
-
|
|
299
292
|
def trim(
|
|
300
293
|
self,
|
|
301
294
|
input_file: str,
|
|
302
295
|
output_file: str,
|
|
303
296
|
start: float = 0,
|
|
304
297
|
duration: float | None = None,
|
|
305
|
-
) ->
|
|
298
|
+
) -> None:
|
|
306
299
|
"""
|
|
307
300
|
Trim a video file.
|
|
308
301
|
|
|
@@ -316,9 +309,6 @@ in your system PATH.
|
|
|
316
309
|
duration: Duration in seconds, or None for remaining video.
|
|
317
310
|
Defaults to None.
|
|
318
311
|
|
|
319
|
-
Returns:
|
|
320
|
-
bytes: FFMPEG output (stdout or stderr) as bytes.
|
|
321
|
-
|
|
322
312
|
Raises:
|
|
323
313
|
FileNotFoundError: If input file doesn't exist.
|
|
324
314
|
ValueError: If start is negative or duration is non-positive.
|
|
@@ -326,24 +316,20 @@ in your system PATH.
|
|
|
326
316
|
|
|
327
317
|
Example:
|
|
328
318
|
>>> # Trim from 5 seconds to 10 seconds (5-second clip)
|
|
329
|
-
>>>
|
|
330
|
-
...
|
|
331
|
-
>>> print(output.decode())
|
|
319
|
+
>>> ffmpeg.trim("video.mp4", "clip.mp4",
|
|
320
|
+
... start=5, duration=5)
|
|
332
321
|
|
|
333
322
|
>>> # Trim from 10 seconds to the end of video
|
|
334
|
-
>>>
|
|
335
|
-
...
|
|
336
|
-
>>> print(output.decode())
|
|
323
|
+
>>> ffmpeg.trim("video.mp4", "ending.mp4",
|
|
324
|
+
... start=10)
|
|
337
325
|
|
|
338
326
|
>>> # Trim first 30 seconds of video
|
|
339
|
-
>>>
|
|
340
|
-
...
|
|
341
|
-
>>> print(output.decode())
|
|
327
|
+
>>> ffmpeg.trim("video.mp4", "intro.mp4",
|
|
328
|
+
... start=0, duration=30)
|
|
342
329
|
|
|
343
330
|
>>> # Trim with floating point precision
|
|
344
|
-
>>>
|
|
345
|
-
...
|
|
346
|
-
>>> print(output.decode())
|
|
331
|
+
>>> ffmpeg.trim("video.mp4", "precise.mp4",
|
|
332
|
+
... start=2.5, duration=3.75)
|
|
347
333
|
"""
|
|
348
334
|
input_path = Path(input_file)
|
|
349
335
|
output_path = Path(output_file)
|
|
@@ -377,4 +363,164 @@ in your system PATH.
|
|
|
377
363
|
f"Trimmed video was not created: {output_file}"
|
|
378
364
|
)
|
|
379
365
|
|
|
380
|
-
|
|
366
|
+
def trims(self, input_bytes: bytes,
|
|
367
|
+
start: float = 0,
|
|
368
|
+
duration: float | None = None,
|
|
369
|
+
format_type: str = "mp4") -> bytes:
|
|
370
|
+
"""
|
|
371
|
+
Trim video data from bytes (in-memory processing).
|
|
372
|
+
|
|
373
|
+
Extracts a segment from in-memory video data starting at a specified time
|
|
374
|
+
and optionally ending after a specified duration. This method is useful
|
|
375
|
+
when you have video data in memory and want to avoid writing temporary files.
|
|
376
|
+
|
|
377
|
+
Note: For MP4 format, this method uses libx264 video codec and AAC audio codec
|
|
378
|
+
with fragmented MP4 output for better streaming compatibility.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
input_bytes: Video data as bytes to trim.
|
|
382
|
+
start: Start time in seconds. Defaults to 0.
|
|
383
|
+
duration: Duration in seconds, or None for remaining video.
|
|
384
|
+
Defaults to None.
|
|
385
|
+
format_type: Output format (e.g., 'mp4', 'avi', 'mov'). Defaults to 'mp4'.
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
bytes: The trimmed video data as bytes.
|
|
389
|
+
|
|
390
|
+
Raises:
|
|
391
|
+
RuntimeError: If video trimming fails.
|
|
392
|
+
|
|
393
|
+
Example:
|
|
394
|
+
>>> # Read video data from a file
|
|
395
|
+
>>> with open("video.mp4", "rb") as f:
|
|
396
|
+
... video_data = f.read()
|
|
397
|
+
>>>
|
|
398
|
+
>>> # Trim first 30 seconds in memory
|
|
399
|
+
>>> trimmed_data = ffmpeg.trims(video_data, start=0, duration=30)
|
|
400
|
+
>>>
|
|
401
|
+
>>> # Save the trimmed video
|
|
402
|
+
>>> with open("intro.mp4", "wb") as f:
|
|
403
|
+
... f.write(trimmed_data)
|
|
404
|
+
>>>
|
|
405
|
+
>>> # Trim with different format
|
|
406
|
+
>>> webm_data = ffmpeg.trims(video_data, start=10, duration=5, format_type="webm")
|
|
407
|
+
>>> with open("clip.webm", "wb") as f:
|
|
408
|
+
... f.write(webm_data)
|
|
409
|
+
>>>
|
|
410
|
+
>>> # Trim with specific codec settings
|
|
411
|
+
>>> # For non-MP4 formats, FFMPEG will use default codecs
|
|
412
|
+
>>> avi_data = ffmpeg.trims(video_data, start=5, duration=10, format_type="avi")
|
|
413
|
+
"""
|
|
414
|
+
args = [
|
|
415
|
+
"-y",
|
|
416
|
+
"-i", "pipe:0",
|
|
417
|
+
"-ss", str(start)
|
|
418
|
+
]
|
|
419
|
+
|
|
420
|
+
if duration is not None:
|
|
421
|
+
args.extend(["-t", str(duration)])
|
|
422
|
+
|
|
423
|
+
if format_type == 'mp4':
|
|
424
|
+
args.extend([
|
|
425
|
+
"-c:v", "libx264",
|
|
426
|
+
"-pix_fmt", "yuv420p",
|
|
427
|
+
"-c:a", "aac",
|
|
428
|
+
"-movflags", "frag_keyframe+empty_moov"
|
|
429
|
+
])
|
|
430
|
+
|
|
431
|
+
args.extend([
|
|
432
|
+
"-f", format_type,
|
|
433
|
+
"pipe:1"
|
|
434
|
+
])
|
|
435
|
+
|
|
436
|
+
stdout, stderr = self.execute(*args, input_data=input_bytes)
|
|
437
|
+
|
|
438
|
+
return stdout
|
|
439
|
+
|
|
440
|
+
def extract_audio(self, input_file: str, output_file: str) -> None:
|
|
441
|
+
"""
|
|
442
|
+
Extract audio from a video file.
|
|
443
|
+
|
|
444
|
+
Extracts the audio track from a video file without re-encoding,
|
|
445
|
+
preserving the original audio quality. The output file extension
|
|
446
|
+
should match the audio codec (e.g., .m4a for AAC, .mp3 for MP3,
|
|
447
|
+
.ogg for Vorbis).
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
input_file: Path to the input video file.
|
|
451
|
+
output_file: Path for the output audio file.
|
|
452
|
+
|
|
453
|
+
Raises:
|
|
454
|
+
FileNotFoundError: If input file doesn't exist.
|
|
455
|
+
RuntimeError: If audio extraction fails.
|
|
456
|
+
|
|
457
|
+
Example:
|
|
458
|
+
>>> # Extract audio from MP4 video
|
|
459
|
+
>>> ffmpeg.extract_audio("video.mp4", "audio.m4a")
|
|
460
|
+
>>>
|
|
461
|
+
>>> # Extract audio and convert to MP3
|
|
462
|
+
>>> ffmpeg.execute("-i", "video.mp4", "-q:a", "0", "-map", "a", "audio.mp3")
|
|
463
|
+
>>>
|
|
464
|
+
>>> # Extract audio from multiple formats
|
|
465
|
+
>>> ffmpeg.extract_audio("movie.mkv", "audio.m4a")
|
|
466
|
+
>>> ffmpeg.extract_audio("clip.avi", "audio.mp3")
|
|
467
|
+
"""
|
|
468
|
+
input_path = Path(input_file)
|
|
469
|
+
output_path = Path(output_file)
|
|
470
|
+
|
|
471
|
+
if not input_path.exists():
|
|
472
|
+
raise FileNotFoundError(
|
|
473
|
+
f"Input file {input_file} was not found."
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
self.execute(
|
|
477
|
+
"-i", str(input_path), # Specifies the input video file.
|
|
478
|
+
"-vn", # Disables the video stream (drops the visual data).
|
|
479
|
+
"-c:a", "copy", # Copies the audio track as-is without re-encoding.
|
|
480
|
+
str(output_path) # Output file. Extension should match audio codec.
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
def extract_audios(self, input_bytes: bytes, output_format: str = "m4a") -> bytes:
|
|
484
|
+
"""
|
|
485
|
+
Extract audio from video data (in-memory processing).
|
|
486
|
+
|
|
487
|
+
Extracts the audio track from in-memory video data without re-encoding,
|
|
488
|
+
preserving the original audio quality. This method is useful when you
|
|
489
|
+
have video data in memory and want to avoid writing temporary files.
|
|
490
|
+
|
|
491
|
+
Args:
|
|
492
|
+
input_bytes: Video data as bytes to extract audio from.
|
|
493
|
+
output_format: Audio output format (e.g., 'm4a', 'mp3', 'ogg', 'wav').
|
|
494
|
+
Defaults to 'm4a'.
|
|
495
|
+
|
|
496
|
+
Returns:
|
|
497
|
+
bytes: The extracted audio data as bytes.
|
|
498
|
+
|
|
499
|
+
Raises:
|
|
500
|
+
RuntimeError: If audio extraction fails.
|
|
501
|
+
|
|
502
|
+
Example:
|
|
503
|
+
>>> # Read video data from a file
|
|
504
|
+
>>> with open("video.mp4", "rb") as f:
|
|
505
|
+
... video_data = f.read()
|
|
506
|
+
>>>
|
|
507
|
+
>>> # Extract audio in memory
|
|
508
|
+
>>> audio_data = ffmpeg.extract_audios(video_data, output_format="m4a")
|
|
509
|
+
>>>
|
|
510
|
+
>>> # Save the extracted audio
|
|
511
|
+
>>> with open("audio.m4a", "wb") as f:
|
|
512
|
+
... f.write(audio_data)
|
|
513
|
+
>>>
|
|
514
|
+
>>> # Extract audio in different formats
|
|
515
|
+
>>> mp3_data = ffmpeg.extract_audios(video_data, output_format="mp3")
|
|
516
|
+
>>> ogg_data = ffmpeg.extract_audios(video_data, output_format="ogg")
|
|
517
|
+
"""
|
|
518
|
+
args = [
|
|
519
|
+
"-i", "pipe:0",
|
|
520
|
+
"-vn",
|
|
521
|
+
"-c:a", "copy",
|
|
522
|
+
"-f", output_format,
|
|
523
|
+
"pipe:1"
|
|
524
|
+
]
|
|
525
|
+
|
|
526
|
+
return self.execute(*args, input_data=input_bytes)[0]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Pipe:
|
|
5
|
+
"""
|
|
6
|
+
A utility class for piping bytes through multiple processing functions.
|
|
7
|
+
|
|
8
|
+
This class provides a convenient way to chain multiple byte-processing
|
|
9
|
+
operations together, creating a pipeline that transforms data step by step.
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
>>> from ffmpeg_python_helper import FFMPEG, Pipe
|
|
13
|
+
>>> ffmpeg = FFMPEG()
|
|
14
|
+
>>>
|
|
15
|
+
>>> # Define processing functions
|
|
16
|
+
>>> def trim_first_30s(data: bytes) -> bytes:
|
|
17
|
+
... return ffmpeg.trims(data, start=0, duration=30)
|
|
18
|
+
>>>
|
|
19
|
+
>>> def convert_to_gif(data: bytes) -> bytes:
|
|
20
|
+
... return ffmpeg.gifs(data, fps=15, scale=480)
|
|
21
|
+
>>>
|
|
22
|
+
>>> def extract_audio(data: bytes) -> bytes:
|
|
23
|
+
... return ffmpeg.extract_audios(data, output_format="m4a")
|
|
24
|
+
>>>
|
|
25
|
+
>>> # Read video data
|
|
26
|
+
>>> with open("video.mp4", "rb") as f:
|
|
27
|
+
... video_data = f.read()
|
|
28
|
+
>>>
|
|
29
|
+
>>> # Create a processing pipeline
|
|
30
|
+
>>> # Trim → Convert to GIF → Extract audio
|
|
31
|
+
>>> result = Pipe.pipe_bytes(
|
|
32
|
+
... video_data,
|
|
33
|
+
... trim_first_30s,
|
|
34
|
+
... convert_to_gif,
|
|
35
|
+
... extract_audio
|
|
36
|
+
... )
|
|
37
|
+
>>>
|
|
38
|
+
>>> # Save the final result (audio from trimmed GIF-converted video)
|
|
39
|
+
>>> with open("processed_audio.m4a", "wb") as f:
|
|
40
|
+
... f.write(result)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def pipe_bytes(initial_value: bytes, *fn: Callable[[bytes], bytes]) -> bytes:
|
|
45
|
+
"""
|
|
46
|
+
Pipe bytes through multiple processing functions.
|
|
47
|
+
|
|
48
|
+
This method takes an initial bytes value and passes it through
|
|
49
|
+
a series of functions, using the output of each function as the
|
|
50
|
+
input to the next function in the chain.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
initial_value: The initial bytes to start the pipeline with.
|
|
54
|
+
*fn: One or more callable functions that take bytes as input
|
|
55
|
+
and return bytes as output. Functions are applied in
|
|
56
|
+
the order they are provided.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
bytes: The final result after passing through all functions.
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
TypeError: If any function is not callable or doesn't accept bytes.
|
|
63
|
+
RuntimeError: If any function in the pipeline fails.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> # Simple pipeline: read, process, save
|
|
67
|
+
>>> def add_header(data: bytes) -> bytes:
|
|
68
|
+
... return b"HEADER" + data
|
|
69
|
+
>>>
|
|
70
|
+
>>> def add_footer(data: bytes) -> bytes:
|
|
71
|
+
... return data + b"FOOTER"
|
|
72
|
+
>>>
|
|
73
|
+
>>> def uppercase_data(data: bytes) -> bytes:
|
|
74
|
+
... return data.upper()
|
|
75
|
+
>>>
|
|
76
|
+
>>> # Create pipeline
|
|
77
|
+
>>> result = Pipe.pipe_bytes(
|
|
78
|
+
... b"hello world",
|
|
79
|
+
... add_header,
|
|
80
|
+
... uppercase_data,
|
|
81
|
+
... add_footer
|
|
82
|
+
... )
|
|
83
|
+
>>>
|
|
84
|
+
>>> print(result)
|
|
85
|
+
b'HEADERHELLO WORLD FOOTER'
|
|
86
|
+
|
|
87
|
+
>>> # FFMPEG processing pipeline
|
|
88
|
+
>>> from ffmpeg_python_helper import FFMPEG
|
|
89
|
+
>>> ffmpeg = FFMPEG()
|
|
90
|
+
>>>
|
|
91
|
+
>>> def trim_video(data: bytes) -> bytes:
|
|
92
|
+
... return ffmpeg.trims(data, start=10, duration=5)
|
|
93
|
+
>>>
|
|
94
|
+
>>> def convert_to_webm(data: bytes) -> bytes:
|
|
95
|
+
... return ffmpeg.trims(data, format_type="webm") # Re-encode as webm
|
|
96
|
+
>>>
|
|
97
|
+
>>> # Process video through pipeline
|
|
98
|
+
>>> with open("input.mp4", "rb") as f:
|
|
99
|
+
... video_data = f.read()
|
|
100
|
+
>>>
|
|
101
|
+
>>> processed_data = Pipe.pipe_bytes(
|
|
102
|
+
... video_data,
|
|
103
|
+
... trim_video,
|
|
104
|
+
... convert_to_webm
|
|
105
|
+
... )
|
|
106
|
+
>>>
|
|
107
|
+
>>> with open("output.webm", "wb") as f:
|
|
108
|
+
... f.write(processed_data)
|
|
109
|
+
"""
|
|
110
|
+
current: bytes = initial_value
|
|
111
|
+
for callable in fn:
|
|
112
|
+
current = callable(current)
|
|
113
|
+
|
|
114
|
+
return current
|