2020-01-08 00:39:49 +00:00
|
|
|
#!/usr/bin/python3
|
|
|
|
"""
|
|
|
|
mkvmerge required (python-pymkv)
|
2020-01-08 01:36:20 +00:00
|
|
|
ffmpeg required
|
|
|
|
TODO:
|
2020-01-08 22:43:20 +00:00
|
|
|
DONE make encoding queue with limiting by workers
|
|
|
|
DONE make concatenating videos after encoding
|
2020-01-09 14:54:01 +00:00
|
|
|
DONE make passing your arguments for encoding,
|
2020-01-08 01:52:57 +00:00
|
|
|
make separate audio and encode it separately,
|
2020-01-08 00:39:49 +00:00
|
|
|
"""
|
|
|
|
|
2020-01-08 00:20:18 +00:00
|
|
|
import os
|
|
|
|
import subprocess
|
2020-01-09 14:54:01 +00:00
|
|
|
import argparse
|
2020-01-09 15:50:26 +00:00
|
|
|
import time
|
2020-01-09 16:25:27 +00:00
|
|
|
import shutil
|
2020-01-08 20:44:44 +00:00
|
|
|
from multiprocessing import Pool
|
2020-01-08 18:56:47 +00:00
|
|
|
try:
|
|
|
|
import scenedetect
|
|
|
|
except:
|
|
|
|
print('ERROR: No PyScenedetect installed, try: sudo pip install scenedetect')
|
2020-01-08 00:20:18 +00:00
|
|
|
|
|
|
|
|
2020-01-09 15:49:28 +00:00
|
|
|
def arg_parsing():
|
|
|
|
"""
|
|
|
|
Command line parser
|
|
|
|
"""
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('--encoding_params', type=str,
|
|
|
|
default=' -an -c:v libaom-av1 -strict -2 -row-mt 1 -tiles 2x2 -cpu-used 8 -crf 60 ',
|
|
|
|
help='FFmpeg settings')
|
|
|
|
parser.add_argument('--input_file', '-i', type=str, default='bruh.mp4', help='input video file')
|
|
|
|
parser.add_argument('--num_worker', '-t', type=int, default=8, help='number of encode running at a time')
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
|
|
|
2020-01-08 00:20:18 +00:00
|
|
|
def get_cpu_count():
|
|
|
|
return os.cpu_count()
|
|
|
|
|
|
|
|
|
|
|
|
def get_ram():
|
|
|
|
return round((os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')) / (1024. ** 3), 3)
|
|
|
|
|
|
|
|
|
2020-01-08 22:43:20 +00:00
|
|
|
def extract_audio(input_vid):
|
2020-01-09 15:50:26 +00:00
|
|
|
"""
|
|
|
|
Extracting audio from video file
|
|
|
|
"""
|
2020-01-08 22:43:20 +00:00
|
|
|
cmd = f'ffmpeg -i {os.getcwd()}/{input_vid} -vn -acodec copy {os.getcwd()}/temp/audio.aac'
|
2020-01-09 16:24:37 +00:00
|
|
|
subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).wait()
|
2020-01-08 22:43:20 +00:00
|
|
|
|
|
|
|
|
2020-01-08 00:39:49 +00:00
|
|
|
def split_video(input_vid):
|
2020-01-08 21:16:53 +00:00
|
|
|
cmd2 = f'scenedetect -i {input_vid} --output temp/split detect-content split-video -c'
|
2020-01-08 00:39:49 +00:00
|
|
|
subprocess.call(cmd2, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
2020-01-09 15:52:11 +00:00
|
|
|
print(f'Video {input_vid} splitted')
|
2020-01-08 00:20:18 +00:00
|
|
|
|
2020-01-08 18:56:47 +00:00
|
|
|
|
|
|
|
def get_video_queue(source_path):
|
|
|
|
videos = []
|
|
|
|
for root, dirs, files in os.walk(source_path):
|
|
|
|
for file in files:
|
|
|
|
f = os.path.getsize(os.path.join(root, file))
|
|
|
|
videos.append([file, f])
|
|
|
|
|
|
|
|
videos = sorted(videos, key=lambda x: -x[1])
|
|
|
|
return videos
|
2020-01-08 20:44:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
def encode(commands):
|
2020-01-09 15:33:47 +00:00
|
|
|
"""
|
|
|
|
Passing encoding params to ffmpeg for encoding
|
|
|
|
TODO:
|
|
|
|
Replace ffmpeg with aomenc because ffmpeg libaom doen't work with parameters properly
|
|
|
|
"""
|
2020-01-08 20:44:44 +00:00
|
|
|
cmd = f'ffmpeg {commands}'
|
2020-01-09 15:52:11 +00:00
|
|
|
print('Started encode process...')
|
2020-01-08 22:43:20 +00:00
|
|
|
subprocess.Popen(cmd, shell=True).wait()
|
2020-01-09 15:52:11 +00:00
|
|
|
print('Finished encode process')
|
2020-01-08 22:43:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
def concat():
|
|
|
|
"""
|
|
|
|
Using FFMPEG to concatenate all encoded videos to 1 file.
|
|
|
|
Reading all files in A-Z order and saving it to concat.txt
|
|
|
|
"""
|
|
|
|
with open(f'{os.getcwd()}/temp/concat.txt', 'w') as f:
|
2020-01-08 20:44:44 +00:00
|
|
|
|
2020-01-08 23:15:17 +00:00
|
|
|
for root, firs, files in os.walk(f'{os.getcwd()}/temp/encode'):
|
2020-01-08 22:43:20 +00:00
|
|
|
for file in sorted(files):
|
|
|
|
f.write(f"file '{os.path.join(root, file)}'\n")
|
2020-01-08 20:44:44 +00:00
|
|
|
|
2020-01-09 16:24:37 +00:00
|
|
|
cmd = f'ffmpeg -f concat -safe 0 -i {os.getcwd()}/temp/concat.txt -i {os.getcwd()}/temp/audio.aac -c copy output.mp4'
|
2020-01-08 22:43:20 +00:00
|
|
|
subprocess.Popen(cmd, shell=True).wait()
|
2020-01-09 15:52:11 +00:00
|
|
|
print('File finished')
|
2020-01-08 21:27:21 +00:00
|
|
|
|
|
|
|
|
2020-01-09 14:54:01 +00:00
|
|
|
def main(input_video, encoding_params, num_worker):
|
2020-01-08 21:27:21 +00:00
|
|
|
|
|
|
|
# Make temporal directories
|
2020-01-08 21:16:53 +00:00
|
|
|
os.makedirs(f'{os.getcwd()}/temp/split', exist_ok=True)
|
2020-01-08 23:15:17 +00:00
|
|
|
os.makedirs(f'{os.getcwd()}/temp/encode', exist_ok=True)
|
2020-01-08 21:27:21 +00:00
|
|
|
|
2020-01-09 16:24:37 +00:00
|
|
|
# Extracting audio
|
|
|
|
extract_audio(input_video)
|
|
|
|
|
2020-01-08 21:27:21 +00:00
|
|
|
# Spliting video and sorting big-first
|
2020-01-08 20:44:44 +00:00
|
|
|
split_video(input_video)
|
|
|
|
vid_queue = get_video_queue('temp')
|
|
|
|
files = [i[0] for i in vid_queue[:-1]]
|
2020-01-08 21:27:21 +00:00
|
|
|
|
|
|
|
# Making list of commands for encoding
|
2020-01-08 23:15:17 +00:00
|
|
|
commands = [f'-i {os.getcwd()}/temp/split/{file} {encoding_params} {os.getcwd()}/temp/encode/{file}' for file in files]
|
2020-01-08 21:27:21 +00:00
|
|
|
|
|
|
|
# Creating threading pool to encode fixed amount of files at the same time
|
2020-01-09 14:54:01 +00:00
|
|
|
pool = Pool(num_worker)
|
2020-01-08 20:44:44 +00:00
|
|
|
pool.map(encode, commands)
|
|
|
|
|
2020-01-08 22:43:20 +00:00
|
|
|
# Merging all encoded videos to 1
|
|
|
|
concat()
|
2020-01-08 20:44:44 +00:00
|
|
|
|
2020-01-08 23:36:39 +00:00
|
|
|
|
2020-01-08 20:44:44 +00:00
|
|
|
if __name__ == '__main__':
|
2020-01-09 15:33:47 +00:00
|
|
|
|
|
|
|
# Command line parser
|
2020-01-09 14:54:01 +00:00
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('--encoding_params', type=str, default=' -an -c:v libaom-av1 -strict -2 -row-mt 1 -tiles 2x2 -cpu-used 8 -crf 60 ', help='FFmpeg settings')
|
|
|
|
parser.add_argument('--input_file', '-i', type=str, default='bruh.mp4', help='input video file')
|
2020-01-09 14:58:05 +00:00
|
|
|
parser.add_argument('--num_worker', '-t', type=int, default=8, help='number of encode running at a time')
|
2020-01-09 15:49:28 +00:00
|
|
|
|
|
|
|
args = arg_parsing()
|
2020-01-09 15:33:47 +00:00
|
|
|
|
|
|
|
# Main thread
|
2020-01-09 15:49:28 +00:00
|
|
|
start = time.time()
|
|
|
|
main(args.input_file, args.encoding_params, args.num_worker)
|
|
|
|
print(f'Encoding completed in {round(time.time()-start)}ces')
|
2020-01-09 16:25:27 +00:00
|
|
|
|
|
|
|
# Delete temp folders
|
|
|
|
shutil.rmtree(f'{os.getcwd()}/temp')
|