-
Notifications
You must be signed in to change notification settings - Fork 8
/
4-multiproc_pipe_to_stream_ffmpeg.py
92 lines (80 loc) · 2.91 KB
/
4-multiproc_pipe_to_stream_ffmpeg.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import os
import cv2
import sys
import time
import psutil
import argparse
import numpy as np
import subprocess as sp
import multiprocessing as mp
# encode_buf_size = psutil.virtual_memory()[4]*0.5//num_processes
def process_video(group_number):
cap = cv2.VideoCapture(args.input_file)
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_jump_unit * group_number)
proc_frames = 0
FIFO_PATH = FIFO_PATHs[group_number]
pipe = sp.Popen(
command + [FIFO_PATH], stdin=sp.PIPE, stderr=sp.PIPE
) # Adding the FIFO_PATH makes ffmpeg redirect the output to the appropriate pipe
while proc_frames < frame_jump_unit:
ret, frame = cap.read()
if ret == False:
break
pipe.stdin.write(cv2.filter2D(frame, -1, kernel).tobytes())
pipe.stdin.flush()
# print('test', group_number)
proc_frames += 1
cap.release()
pipe.communicate(b"q") # ffmpeg closes the stream on entering 'q'
os.unlink(FIFO_PATH)
return None
if __name__ == "__main__":
kernel = np.ones((7,7),np.float32)/49
parser = argparse.ArgumentParser()
parser.add_argument("--input_file", default="Kiiara.mp4", type=str)
parser.add_argument("--extra_flags", default="", type=str)
args = parser.parse_args()
num_processes = mp.cpu_count()
start_time = time.time()
cap = cv2.VideoCapture(args.input_file)
frame_jump_unit = cap.get(cv2.CAP_PROP_FRAME_COUNT) // num_processes
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
cap.release()
FIFO_PATHs = tuple("/tmp/my_fifo_{}".format(i) for i in range(num_processes))
for FIFO_PATH in FIFO_PATHs:
if os.path.exists(FIFO_PATH):
os.unlink(FIFO_PATH)
os.mkfifo(FIFO_PATH)
FFMPEG_BIN = "ffmpeg" # on Linux ans Mac OS
command = [
FFMPEG_BIN,
"-y", # (optional) overwrite output file if it exists
"-loglevel", "warning",
"-f", "rawvideo",
"-vcodec", "rawvideo",
"-s", "{}x{}".format(width, height), # size of one frame
"-pix_fmt", "bgr24",
"-r", str(fps), # frames per second
"-i", "-", # The imput comes from a pipe
"-an", # Tells FFMPEG not to expect any audio
"-r", str(fps),
"-vcodec", "libx264",
"-f", "mpegts", ]
command.extend(args.extra_flags.split())
p = mp.Pool(num_processes)
r = p.map_async(process_video, range(num_processes))
sp.Popen(
'ffmpeg -y -loglevel warning -f mpegts -i "concat:{}" -an -vcodec copy -use_wallclock_as_timestamps 1 {} output_method4.mp4'.format(
"|".join(FIFO_PATHs), args.extra_flags
),
shell=True,
)
r.wait()
t2 = time.time()
print(
"Method {}: Input:{}, extra_flags:{}, Time taken: {}".format(
sys.argv[0], args.input_file, args.extra_flags, t2 - start_time
)
)