Music-Library/extractor.py
2024-04-15 13:21:43 +00:00

177 lines
4.4 KiB
Python

import os, json
import traceback
def escape_file_name(fname):
"""
Helper function to safely convert the file name (a.k.a. escaping) with
spaces which can cause issues when passing over to the command line.
"""
result = fname.replace('\"', '\\"') # escapes double quotes first
result = ['"',result,'"']
return "".join(result)
def BytesToReadable(bytes):
sizes = ["B", "KB", "MB", "GB", "TB"]
i = 0
while bytes > 1024:
bytes = bytes / 1024
i += 1
return f"{bytes:.2f} {sizes[i]}"
def get_file_size(file_path):
"""
Returns the size of the file in bytes.
"""
return os.path.getsize(file_path)
import subprocess
def CheckFFPROBE():
try:
process=subprocess.Popen(
" ".join(["ffprobe", "-version"]),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True
)
output = process.stdout.readlines()
err = process.stderr.readlines()
if output == []:
err_msg = "".join(err)
raise Exception("Error while invoking ffprobe:\n" + err_msg)
return True
except Exception as e:
return False
except:
pass
return
def CheckFFMPEG():
try:
process=subprocess.Popen(
" ".join(["ffmpeg", "-version"]),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True
)
output = process.stdout.readlines()
err = process.stderr.readlines()
if output == []:
err_msg = "".join(err)
raise Exception("Error while invoking ffmpeg:\n" + err_msg)
return True
except Exception as e:
return False
except:
pass
return
class ExtractorException(Exception):
def __init__(self, errors):
self.errors = errors
def __str__(self):
return repr(self.errors)
def ExtractMetadata(file):
print("Extracting Metadata: ", file)
AdvancedData = {
"file:" : file,
"data": "Unknown",
}
test = CheckFFPROBE()
if not test:
print("### FFPROBE: Check failed ###")
e = ExtractorException("FFPROBE not found or not installed.")
raise e
try:
escaped_fpath = escape_file_name(file)
process=subprocess.Popen(
" ".join(["ffprobe",
"-show_entries format_tags",
"-print_format json",
escaped_fpath],),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True
)
output = process.stdout.readlines()
err = process.stderr.readlines()
if output == []:
err_msg = "".join(err)
raise Exception("Error while invoking ffprobe: " + err_msg)
ffprobe_json = []
skip_line = True
# cleanse any additional information that is not valid JSON
for line in output:
# string out b' and \r\n
line = line.decode("utf-8")
if line.strip() == '{':
skip_line = False
if not skip_line:
ffprobe_json.append(line)
result = json.loads("".join(ffprobe_json))
return result
except Exception as e:
print("### Extractor Error ###")
print(e)
except:
pass
return AdvancedData
def ExtractMediaData(file, output_file):
"""
Extracts media data from a file using ffmpeg.
"""
try:
escaped_fpath = escape_file_name(file)
# get the absolute path to the output file
current_dir = os.getcwd()
absout = os.path.join(current_dir, output_file)
if os.path.exists(absout):
return absout
print("Extracting Media Data: ", file)
subprocess.Popen(
" ".join(["ffmpeg",
"-i",
escaped_fpath,
"-an",
"-vcodec",
"copy",
f'"{absout}"'],), # output file should be in quotes to avoid spaces in the path 'E:\Downloads\4kvideodownloader\video.mp4
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True
)
return absout
except Exception as e:
print("### Extractor Error ###")
traceback.print_exc()
except:
pass