Skip to content

Instantly share code, notes, and snippets.

@AmirSbss
Last active March 25, 2023 05:37
Show Gist options
  • Select an option

  • Save AmirSbss/173ba6dc3157fd711d50e2e516bddc7b to your computer and use it in GitHub Desktop.

Select an option

Save AmirSbss/173ba6dc3157fd711d50e2e516bddc7b to your computer and use it in GitHub Desktop.
FFMpeg tools in python with progress callback
from ffmpeg import *
def progress(duration, time, process_name):
print(f"{time} from {duration} seconds is fixed, Process name: {process_name}")
def streamable(input_file, output_file):
args = ['-movflags', 'faststart', '-strict', '-2']
return ffmpeg(input_file, output_file, args, progress, ["Test Progress!"])
# You can run this in a thread
streamable("input.mp4", "output.mp4")
import socket
import json
import subprocess as sp
import os
from threading import Thread
def probe(vid_file_path: str):
''' Give a json from ffprobe cocmmand line
@vid_file_path : The absolute (full) path of the video file, string.
'''
if type(vid_file_path) != str:
raise Exception('Give ffprobe a full file path of the video')
return
command = ["ffprobe",
"-loglevel", "quiet",
"-print_format", "json",
"-show_format",
"-show_streams",
vid_file_path
]
pipe = sp.Popen(command, stdout=sp.PIPE, stderr=sp.STDOUT)
out, err = pipe.communicate()
return json.loads(out.decode('utf-8'))
def ffmpeg(input_file: str, outputfile: str, options: list=[], progress: None or callable=None, progress_args: list=[]):
duration = 0
width = 0
height = 0
file_data = probe(input_file)
data_received = 0
if 'format' in file_data:
if 'duration' in file_data['format']:
duration = float(file_data['format']['duration'])
if 'width' in file_data['format']:
width = int(file_data['format']['width'])
height = int(file_data['format']['height'])
if 'streams' in file_data:
for s in file_data['streams']:
if 'duration' in s:
duration = float(s['duration'])
if 'width' in s:
width = int(s['width'])
height = int(s['height'])
last_data = {}
if progress:
last_time_progress = 0.0
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("", 0))
s.listen()
port = s.getsockname()[1]
options += ['-progress', 'http://127.0.0.1:{}'.format(port)]
cmd = '''ffmpeg -i {} {} {} > /dev/null 2>&1 &'''.format(input_file, ' '.join(options), outputfile)
os.system(cmd)
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(1024)
data_received += 1
if data_received > 1:
data = data.decode('utf-8')
data = data.replace('\r', '').split('\n')[1:]
for i in data:
if "=" in i:
key, value = i.split("=")
last_data[key] = value
if progress and "out_time_ms" in last_data:
time = int(last_data["out_time_ms"]) / 1000000.0
if time - last_time_progress > 1.0 or last_data.get("progress") == "end":
pargs = [duration, time] + progress_args
Thread(target=progress, args=pargs).start()
last_time_progress = time
if not data:
break
if last_data.get("progress") != "end":
return False
else:
cmd = '''ffmpeg -i {} {} {}'''.format(input_file, ' '.join(options), outputfile)
os.system(cmd)
last_data["duration"] = int(duration)
last_data["width"] = width
last_data["height"] = height
return last_data
@AmirSbss
Copy link
Copy Markdown
Author

AmirSbss commented Jan 6, 2019

Needs ffmpeg installed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment