Av1an/av1an/utils.py

102 lines
2.7 KiB
Python
Raw Normal View History

2020-06-27 19:21:00 +00:00
#!/bin/env python
import re
import sys
2020-08-19 06:47:10 +00:00
from typing import List
2020-06-27 19:21:00 +00:00
from pathlib import Path
import cv2
import numpy as np
import hashlib
2020-12-25 15:32:45 +00:00
from av1an.ffmpeg import frame_probe_ffmpeg
from av1an.vapoursynth import frame_probe_vspipe, is_vapoursynth
2021-05-05 18:11:08 +00:00
from av1an.logger import log
2020-06-14 16:28:00 +00:00
def terminate():
2020-06-27 19:21:00 +00:00
sys.exit(1)
2020-06-22 20:11:07 +00:00
2020-06-13 23:54:54 +00:00
def hash_path(s: str) -> int:
"""
Return hash of full path to file
:param s: string
"""
2021-01-25 00:49:25 +00:00
assert isinstance(s, str)
2021-05-05 18:11:08 +00:00
file_hash = str(hashlib.sha3_512(s.encode()).hexdigest())[-8:]
log(f"File hash: {file_hash}")
2020-06-22 17:03:49 +00:00
2021-05-05 18:11:08 +00:00
return file_hash
2020-06-22 20:11:07 +00:00
2020-06-09 17:22:02 +00:00
def get_cq(command):
2020-07-01 12:43:29 +00:00
"""
Return cq values from command
:param command: string with commands for encoder
:return: list with frame numbers of keyframes
"""
2020-06-09 17:22:02 +00:00
matches = re.findall(r"--cq-level= *([^ ]+?) ", command)
return int(matches[-1])
def list_index_of_regex(lst: List[str], regex_str: str) -> int:
"""
Gets the first index of the list where regex_str matches
:param lst: the list
:param regex_str: the regex as a string
:return: the index where regex_str appears in the list
:raises ValueError: if regex_str is not found
"""
reg = re.compile(regex_str)
for i, elem in enumerate(lst):
if reg.match(elem):
return i
2021-04-12 23:23:48 +00:00
raise ValueError(f"{reg} is not in list")
def frame_probe_fast(source: Path, is_vs: bool = False):
"""
Consolidated function to retrieve the number of frames from the input quickly,
falls back on a slower (but accurate) frame count if a quick count cannot be found.
Handles vapoursynth input as well.
"""
total = 0
if not is_vs:
try:
2021-01-09 00:08:43 +00:00
import vapoursynth
2021-01-24 20:56:19 +00:00
from vapoursynth import core
2021-04-12 23:23:48 +00:00
2021-01-09 00:08:43 +00:00
plugins = vapoursynth.get_core().get_plugins()
2021-04-12 23:23:48 +00:00
if "systems.innocent.lsmas" in plugins:
total = core.lsmas.LWLibavSource(
source.as_posix(), cache=False
).num_frames
2021-05-05 18:11:08 +00:00
log("Get frame count with lsmash")
log(f"Frame count: {total}")
2021-01-24 20:59:36 +00:00
return total
2021-01-09 00:08:43 +00:00
except:
video = cv2.VideoCapture(source.as_posix())
total = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
video.release()
2021-05-05 18:11:08 +00:00
log("Can't open input with Pyscenedetect OpenCV")
if is_vs or total < 1:
total = frame_probe(source)
return total
def frame_probe(source: Path):
"""
Determines the total number of frames in a given input.
Differentiates between a Vapoursynth script and standard video
and delegates to vspipe or ffmpeg respectively.
"""
if is_vapoursynth(source):
return frame_probe_vspipe(source)
return frame_probe_ffmpeg(source)