This repository has been archived on 2024-09-06. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
SimpleVideoExporter/export-video.py

250 lines
7.2 KiB
Python
Executable file

#!/usr/bin/env python
"""
export-video
Little scrip to export video file for The Internet :D
"""
import sys
import getopt
import re
import os
import subprocess
import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
def usage():
""" Print usage"""
print("export-video -i input -o output [-d --desinterlace]")
params = {
"desinterlace": False,
"file_output": "",
"file_input": "",
"vbitrate": "600k",
"abitrate": "96k",
"h264_vcommand": [
"-trellis", "0",
"-me_method", "umh",
"-subq", "8",
"-me_range", "16",
"-bf", "3",
"-rc_lookahead", "16",
"-g", "250"
],
"h264_acommand": ["-strict", "experimental"],
"webm_vcommand": [
"-rc_lookahead", "16",
"-keyint_min", "0"
"-g", "250",
"-skip_threshold", "0",
"-level", "116"
],
"webm_acommand": ["-strict", "experimental"],
"verbose": True,
"pattern": "",
"twopass": False,
"recursive": False}
VERSION = "0.1dev"
def execute(command, shell=False):
"""
Execute a system command and return its results.
Thanxx Strycote from Lutris.net
"""
try:
stdout, stderr = subprocess.Popen(command,
shell=shell,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()
except OSError as ex:
logging.error('Could not run command %s: %s', command, ex)
return
return stdout.strip()
def find_executable(exec_name):
"""
find executable with which command
exec_name (string) : executable to find
"""
if not exec_name:
raise ValueError("find_executable: exec_name required")
return execute(['which', exec_name])
def list_file(directory, pattern, recursive):
"""
list files from a directory
directory (string) : source directory
pattern (string) : regex used to found files
recursive (boolean) : should i serach on sub-folder?
"""
logging.info('searching in directory %s', directory)
files_list = []
try:
dirs = os.listdir(directory)
except OSError:
logging.error('error : %s not a directory?', directory)
return
for i in dirs:
logging.debug(' working on file / dir %s', i)
if os.path.isdir(directory + "/" + i) and recursive:
logging.info('directory found : %s', i)
files_list.extend(list_file(
os.path.join(directory, i),
pattern,
recursive
))
else:
if re.search(pattern, i) is not None:
logging.info('file found : %s', i)
files_list.append(directory + "/" + i)
return files_list
def get_file_name(path):
"""
find basename without extension
path (string) : complete path + file
"""
return os.path.splitext(os.path.basename(path))[0]
def process_arg(sysarg):
"""
Process arguments
sysarg (list) : list of arguments
"""
try:
opts, args = getopt.getopt(
sysarg, "hi:o:dp:a:v:2",
[
"help",
"input=",
"output=",
"desinterlace",
"pattern=",
"abitrate=",
"vbitrate=",
"twopass"
]
)
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit()
if opt in ("-o", "--output"):
params["file_output"] = arg
if opt in ("-d", "--desinterlace"):
logging.info("Desinterlace activated")
params["h264_vcommand"] += ["-vf", "yadif"]
params["webm_vcommand"] += ["-vf", "yadif"]
if opt in ("-i", "--input"):
params["file_input"] = arg
if opt in ("-p", "--pattern"):
params["pattern"] = "^\\w*."+arg+"$"
if opt in ("-a", "--abitrate"):
params["abitrate"] = arg
if opt in ("-v", "--vbitrate"):
params["vbitrate"] = arg
if opt in ("-2", "--twopass"):
params["twopass"] = True
if opt in ("-r", "--recursive"):
params["recursive"] = True
def encode_h264(src, dest):
""" Encode file
src (string) : source video file
dest (string) : destination file
"""
if params["twopass"]:
logging.debug("two pass encoding started ...")
firstpass = [
EXEC_FFMPEG,
"-y",
"-i", src,
"-codec:va", "libx264",
"-b:v", params["vbitrate"],
"-pass", "1",
] + params["h264_vcommand"] + [
"-f", "rawvideo",
"/dev/null"
]
secondpass = [
EXEC_FFMPEG,
"-i", src,
"-pass", "2",
"-codec:v", "libx264",
"-b:v ", params["vbitrate"]
] + params["h264_vcommand"] + [
"-b:a", params["abitrate"]
] + params["h264_acommand"] + [
dest+".mp4"
]
logging.debug("First Pass command %s", firstpass)
execute(firstpass)
logging.debug("Second pass command %s", secondpass)
execute(secondpass)
else:
logging.debug("one pass encoding started ...")
encode = [
EXEC_FFMPEG,
"-i", src,
"-codec:v", "libx264",
"-b:v ", params["vbitrate"]
] + params["h264_vcommand"] + [
"-b:a", params["abitrate"]
] + params["h264_acommand"] + [
dest+".mp4",
]
logging.debug(encode)
execute(encode)
if __name__ == "__main__":
EXEC_FFMPEG = find_executable("ffmpeg")
if not EXEC_FFMPEG:
print('ffmpeg not found, exiting')
sys.exit(2)
process_arg(sys.argv[1:])
if not params["file_input"]:
print("you must specify a file / directory input")
sys.exit(2)
if os.path.isdir(params["file_input"]):
if os.path.isfile(params["file_output"]):
print("Can't batch export to a single file! Bye Bye")
sys.exit(2)
logging.info('%s is a directory', params["file_input"])
video_files = list_file(
params["file_input"],
params["pattern"],
params["recursive"]
)
for f in video_files:
logging.info('batch encode | file %s', f)
encode_h264(f, os.path.join(
params["file_output"], get_file_name(f)
))
else:
if os.path.isfile(params["file_input"]):
if not params["file_output"]:
params["file_output"] = get_file_name(params["file_input"])
else:
if os.path.isdir(params["file_output"]):
params["file_input"] = os.path.join(
params["file_input"],
get_file_name(params["file_input"])
)
logging.info('%s is a file', params["file_input"])
encode_h264(params["file_input"], params["file_output"])
else:
logging.info("input file desn't exist, bye bye")
sys.exit(2)
sys.exit(0)