A fast, flexible Python wrapper for FFmpeg, FFprobe, and FFplay — fetch metadata, encode, split, play and run custom commands easily with real-time progress tracking.
Project description
ffwrapy
ffwrapy is a fast, flexible Python wrapper for FFmpeg, FFprobe, and FFplay — fetch metadata, encode, split, play and run custom commands easily with real-time progress tracking.
Features
- Fetch media info (duration, size, streams) via FFprobe
- Encode with custom codecs, presets, and metadata via FFmpeg
- Split files or split into parts (with/without re-encoding)
- Generate thumbnails from videos
- Custom command execution for ffmpeg, ffprobe, ffplay
- Track naming and title setting
- Progress callback support for long operations (encoding, splitting, etc)
- Pure
subprocess(no dependencies except Python & FFmpeg)
Requirements
- Python 3.x
- FFmpeg, FFprobe, and FFplay installed and available in the system PATH
NOTE: Only FFprobe required at initialisation; FFmpeg required only during associated tasks like encoding, splitting, etc; FFplay required only during associated tasks like playback, etc;
ffmpeg -version
ffprobe -version
ffplay -version
Installation
pip install ffwrapy
Usage
Initialization
from ffwrapy import FFMedia as FFM
media = FFM(
file="input.mp4", # Input file
verbose=True # To trigger any print statements in the script; Default: False
)
Fetching Media Info
print(media.size_mb) # File size in MB
print(media.duration) # Duration in seconds
print(media.audiodata) # Audio tracks info
print(media.videodata) # Video tracks info
print(media.subtitles) # Subtitle tracks info
Preparing to Encode
# Naming Tracks and Title
media.name(
aud_name="ffwrapy_aud", # Name for all audio tracks
vid_name="ffwrapy_vid", # Name for all video tracks
sub_name="ffwrapy_sub", # Name for all subtitle tracks
title="ffwrapy title" # Name for the output video title
) # Default : <the name as defined in input file ie media>
# Defining Preset and Codecs
media.codec_vid = "libx264" # Name for video codec; Default : "libx264"
media.codec_aud = "aac" # Name for audio codec; Default : "aac"
media.codec_sub = "mov_text" # Name for subtitle codec; Default : "mov_text"
media.crf = "23" # Value for crf (0-51); Default : "23"
media.preset = "faster" # Preset to be used; Default : "faster"
media.movflags = "+faststart" # Value for moov atom; Default : "+faststart"
media.max_muxing_queue_size = "99" # Max size for mux queue; Default : "9999"
Encoding
media.encode(
output="output.mp4", # Name for output encoded file
thumb="00:00:05", # Timestamp in "HH:MM:SS" format to generate output.jpg from the processed video at the given time
replace=True, # Overwrite output if exists
)
outputName for output encoded filess: Start time (string or seconds); Default : None (ie from beginning)to: End time (string or seconds); Default : None (ie till ending)thumb: Timestamp in "HH:MM:SS" format to generate output.jpg from the processed video at the given time; Default : None (ie no thumbnail generated)replace: Overwrite output if exists; Default : Falseprogress_callback: Callback function to track progress; Args : (progress as a dict), (process object); Default : Nonecallback_interval: The interval (in seconds) between each callback; Default : 1
Splitting
media.split(
output="output_clip.mp4", # Name for output splitted file
ss="00:01:00", # Start time (string or seconds)
to="00:02:00", # End time (string or seconds)
replace=True, # Overwrite output if exists
)
outputName for output splitted filess: Start time (string or seconds); Default : None (ie from beginning)to: End time (string or seconds); Default : None (ie till ending)thumb: Timestamp in "HH:MM:SS" format to generate output.jpg from the processed video at the given time; Default : None (ie no thumbnail generated)replace: Overwrite output if exists; Default : Falseprogress_callback: Callback function to track progress; Args : (progress as a dict), (process object); Default : Nonecallback_interval: The interval (in seconds) between each callback; Default : 1
Splitting into Parts
media.split_parts(
output = "part.mp4", # Base name for the output
parts=3, # Number of parts to split into
safe_time=5, # Repetion duration (in seconds) between each part to conserve any diversion
reencode=False, # Whether to reencode the file
)
outputBase name for the output; if a string is provided, forms an array with each element as 'i_out' where i is the part name and out is the provided string; if an array is provided, the elements of array are used as the part namepartsNumber of parts to split into; Default : 2safe_timeRepetion duration (in seconds) between each part to conserve any diversion; Default : 5reencode=TrueWhether to reencode the file (accurate but takes time), reencode uses .encode() otherwise .split() is used which is quick but may not be accurate; Default : Falsethumb: Timestamp in "HH:MM:SS" format to generate output.jpg from the processed video at the given time; Default : None (ie no thumbnail generated)replace: Overwrite output if exists; Default : Falseprogress_callback: Callback function to track progress; Args : (progress as dict), (process object), (serial number of part as int); Default : Nonecallback_interval: The interval (in seconds) between each callback; Default : 1
Thumbnail Generation
media.thumbnail(
replace=True # Overwrite output if exists
)
timestampThe timestamp in the input file at which thumbnail is to be generated; Default : "00:00:05"fileThe input filename whose thumbnail is to be generated; Default: None (ie media.file)replace: Overwrite output if exists; Default : False
Playback
media.play(
volume=50, # Playback volume (0 to 100)
audio=1, # Audio stream index to play
)
seek: Start playback after skipping given time (in seconds); Default:0duration: Stop playback after this duration; Default:None(ie till end)volume: Set audio volume for playback in percentage (0–100); Default:50audio: Select audio stream index (as per media) to play; Default : None (ie first available audio stream)video: Select video stream index (as per media) to play; Default : None (ie first available video stream)subtitle: Select subtitle stream index (as per media) to play; Default : None (ie first available subtitle stream)width: Resize the playback window width; Default:None(ie original width)height: Resize the playback window height; Default:None(ie original height)disable_audio: Disable the audio stream playback; Default:Falsedisable_video: Disable the video stream playback; Default:Falsedisable_subtitle: Disable the subtitle stream playback; Default:False
Custom FFmpeg/FFprobe/FFplay Command
media.custom_ffmedia(
customisation=["ffprobe", "-hide_banner", media.file]
)
media.custom_ffm(
customisation=["ffprobe", "-hide_banner", media.file]
) # Same as .custom_ffmedia()
media.custom_ffmedia(
customisation=["ffplay", media.file]
)
media.custom_ffm(
customisation=["ffplay", media.file]
) # Same as .custom_ffmedia()
customisationThe custom cmd array for FFmpeg/FFprobe/FFplay Commandthumb: Timestamp in "HH:MM:SS" format to generate output.jpg from the processed video at the given time; Default : None (ie no thumbnail generated)replace: Overwrite output if exists; Default : Falseprogress_callback: Callback function to track progress; Args : (progress as dict), (process object); Default : Nonecallback_interval: The interval (in seconds) between each callback; Default : 1
Example Workflow
from ffwrapy import FFMedia as FFM
media = FFM("movie.ts", verbose=True)
media.name("HIN", "Main", "HIN Subs", title="Demo Movie")
media.encode("movie.mkv", thumb="00:00:05")
media_encoded = FFM("movie.mkv")
media_encoded.split("movie_clip.mp4", ss="00:10:00", to="00:15:00")
media_encoded.split_parts("movie_part.mp4", parts=4)
media_encoded.thumbnail()
media_encoded.custom_ffmedia(["ffmpeg", "-i", media_encoded.file, "-vn", "-acodec", "copy", "audio.aac"])
media_encoded.play()
Notes
- All operations use subprocess calls to FFmpeg/FFprobe/FFplay; ensure these are installed and accessible.
- Error handling is basic; adapt for production use as needed.
- Extend or modify the class for advanced workflows.
License
Apache License 2.0
This library is open-source and free to use under the Apache 2.0 License.
Contributing
Contributions, suggestions, and feature requests are welcome! Feel free to submit an issue or PR.
Author
Developed by भाग्य ज्योति (Bhagya Jyoti)
Happy media processing!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ffwrapy-1.1.0.tar.gz.
File metadata
- Download URL: ffwrapy-1.1.0.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0b926519e2981ca954cbd707aa794840704076c87ec58d96beb0b20595a0f4b
|
|
| MD5 |
66b6f23710f374e200730c2ef8cea362
|
|
| BLAKE2b-256 |
9d564bb67dde45677300b9ad29c7c9b50ac436a67388f2602ed68b372b91ca13
|
Provenance
The following attestation bundles were made for ffwrapy-1.1.0.tar.gz:
Publisher:
pypi.yml on BhagyaJyoti22006/ffwrapy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ffwrapy-1.1.0.tar.gz -
Subject digest:
f0b926519e2981ca954cbd707aa794840704076c87ec58d96beb0b20595a0f4b - Sigstore transparency entry: 231327076
- Sigstore integration time:
-
Permalink:
BhagyaJyoti22006/ffwrapy@f30fbb98e1b65fffbde9b7a34e1a0f8f0bf93ad7 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/BhagyaJyoti22006
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@f30fbb98e1b65fffbde9b7a34e1a0f8f0bf93ad7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ffwrapy-1.1.0-py3-none-any.whl.
File metadata
- Download URL: ffwrapy-1.1.0-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08637080a0f2fd127dd2e78d943675b08b6a83028d2647d9f44c2f696bc46d9a
|
|
| MD5 |
d4e6c7d35438e4c8ca32c7f7a30fe290
|
|
| BLAKE2b-256 |
9566228d3e75d15561929ba29bdea4cc39f0ff91306f8483ca863085c57b052e
|
Provenance
The following attestation bundles were made for ffwrapy-1.1.0-py3-none-any.whl:
Publisher:
pypi.yml on BhagyaJyoti22006/ffwrapy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ffwrapy-1.1.0-py3-none-any.whl -
Subject digest:
08637080a0f2fd127dd2e78d943675b08b6a83028d2647d9f44c2f696bc46d9a - Sigstore transparency entry: 231327093
- Sigstore integration time:
-
Permalink:
BhagyaJyoti22006/ffwrapy@f30fbb98e1b65fffbde9b7a34e1a0f8f0bf93ad7 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/BhagyaJyoti22006
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@f30fbb98e1b65fffbde9b7a34e1a0f8f0bf93ad7 -
Trigger Event:
release
-
Statement type: