diff --git a/assets/install_ffmpeg.py b/assets/install_ffmpeg.py index da64f7e..b9116af 100644 --- a/assets/install_ffmpeg.py +++ b/assets/install_ffmpeg.py @@ -8,23 +8,25 @@ import time import urllib.request import zipfile + try: import patoolib + AVAILABLE_7Z = True except (ImportError, ModuleNotFoundError): AVAILABLE_7Z = False def get_ffmpeg_url(build=None, format=None) -> str: - ''' + """ Constructs an FFMPEG build download URL Args: build (str): the type of FFMPEG build you want format (str): whether you want a 7z or zip file - ''' - if format == '7z' and not AVAILABLE_7Z: - raise ValueError('7z format unavailable as pyunpack and patool are not present') + """ + if format == "7z" and not AVAILABLE_7Z: + raise ValueError("7z format unavailable as pyunpack and patool are not present") for ffbuild_name, formats in BUILDS.items(): if not (build is None or build == ffbuild_name): @@ -35,26 +37,34 @@ def get_ffmpeg_url(build=None, format=None) -> str: continue if names[0]: - return f'https://gyan.dev/ffmpeg/builds/ffmpeg-{names[0]}.{ffbuild_format}' + return ( + f"https://gyan.dev/ffmpeg/builds/ffmpeg-{names[0]}.{ffbuild_format}" + ) if names[1]: - github_version = urllib.request.urlopen( - 'https://www.gyan.dev/ffmpeg/builds/release-version').read().decode() - assert github_version, 'failed to retreive latest version from github' + github_version = ( + urllib.request.urlopen( + "https://www.gyan.dev/ffmpeg/builds/release-version" + ) + .read() + .decode() + ) + assert github_version, "failed to retreive latest version from github" return ( - 'https://github.com/GyanD/codexffmpeg/releases/download/' - f'{github_version}/ffmpeg-{github_version}-{names[1]}.{ffbuild_format}' + "https://github.com/GyanD/codexffmpeg/releases/download/" + f"{github_version}/ffmpeg-{github_version}-{names[1]}.{ffbuild_format}" ) - raise ValueError(f'{build} as format {format} does not exist') + raise ValueError(f"{build} as format {format} does not exist") -class InstallDirs(): - ''' +class InstallDirs: + """ Takes a URL and an installation directory and generates a number of suggested file paths. - ''' + """ + def __init__(self, url, install_dir): - ''' + """ Args: url (str): the URL to the FFMPEG download install_dir (str): the directory to install FFMPEG to @@ -67,14 +77,18 @@ def __init__(self, url, install_dir): hash_url (str): the URL of the file's expected sha256 hash download_dest (str): the file that the data will be downloaded into unzip_dest (str): the path that the downloaded file will be decompressed into - ''' + """ self.install_dir = os.path.abspath(install_dir) - self.install_path = os.path.join(install_dir, 'FFMPEG') + self.install_path = os.path.join(install_dir, "FFMPEG") self.url = url # can't get checksums from github - self.hash_url = None if url.startswith("https://github.com") else url + '.sha256' + self.hash_url = ( + None if url.startswith("https://github.com") else url + ".sha256" + ) self.download_dest = os.path.join(self.install_path, os.path.basename(self.url)) - self.unzip_dest = self.download_dest.rstrip(os.path.splitext(self.download_dest)[-1]) + self.unzip_dest = self.download_dest.rstrip( + os.path.splitext(self.download_dest)[-1] + ) def get_sha256(fname) -> str: @@ -86,12 +100,12 @@ def get_sha256(fname) -> str: def make_empty_path(path, overwrite=False): - ''' + """ Creates a filepath and makes sure that it is empty Raises: FileExistsError: if the filepath exists AND is not empty - ''' + """ try: os.mkdir(path) except FileExistsError as e: @@ -101,17 +115,18 @@ def make_empty_path(path, overwrite=False): make_empty_path(path, overwrite=False) else: raise FileExistsError( - 'install directory exists and is not empty') from e + "install directory exists and is not empty" + ) from e -class Downloader(): - def __init__(self, url, destination, hash_url=None, mode='default'): - ''' +class Downloader: + def __init__(self, url, destination, hash_url=None, mode="default"): + """ Args: url (str): the URL of the resource to download destination (str): the filepath to save the data to hash_url (str): the URL containing the file's expected hash - ''' + """ self.url = url self.destination = destination if hash_url is not None: @@ -124,41 +139,51 @@ def __init__(self, url, destination, hash_url=None, mode='default'): self.size = data.length def download(self): - ''' + """ Downloads the file Raises: ValueError: if the expected hash does not match the downloaded file's hash - ''' + """ self.failed = False try: - if self.mode == 'windows': + if self.mode == "windows": subprocess.check_output( - ['powershell', '-Command', 'Invoke-WebRequest', self.url, '-OutFile', self.destination] + [ + "powershell", + "-Command", + "Invoke-WebRequest", + self.url, + "-OutFile", + self.destination, + ] ) - elif self.mode == 'wget': + elif self.mode == "wget": # use command prompt because powershell aliases wget to Invoke-WebRequest, which is much slower try: subprocess.check_output( - ['cmd', '/c', 'wget', self.url, '-O', self.destination, '-q'] + ["cmd", "/c", "wget", self.url, "-O", self.destination, "-q"] ) except (FileNotFoundError, subprocess.CalledProcessError) as e: - print('Error calling wget:', e.stderr if isinstance(e, subprocess.CalledProcessError) else e) + print( + "Error calling wget:", + e.stderr if isinstance(e, subprocess.CalledProcessError) else e, + ) raise Exception( - 'Call to wget failed.' - ' By default Windows sets wget as an alias of Invoke-WebRequest.' - ' Make sure you have GNU wget installed and on your PATH' + "Call to wget failed." + " By default Windows sets wget as an alias of Invoke-WebRequest." + " Make sure you have GNU wget installed and on your PATH" ) from e - elif self.mode == 'curl': + elif self.mode == "curl": # again, use CMD because of the alias problem. Don't need correct version warning here # since windows now ships with curl subprocess.check_output( - ['cmd', '/c', 'curl', '-sLo', self.destination, self.url] + ["cmd", "/c", "curl", "-sLo", self.destination, self.url] ) else: - with open(self.destination, 'wb') as f: + with open(self.destination, "wb") as f: with urllib.request.urlopen(self.url) as data: - while (chunk := data.read(4096)): + while chunk := data.read(4096): f.write(chunk) if self.hash is None: @@ -166,22 +191,22 @@ def download(self): if self.hash != get_sha256(self.destination): self.failed = True - raise ValueError('downloaded file does not match expected hash') + raise ValueError("downloaded file does not match expected hash") except Exception: self.failed = True raise def progress(self) -> int: - '''Returns number of downloaded bytes''' + """Returns number of downloaded bytes""" if not os.path.isfile(self.destination): return 0 return os.path.getsize(self.destination) def download_ffmpeg(dirs: InstallDirs, mode: str): - '''Download the ffmpeg archive and print progress to the console''' + """Download the ffmpeg archive and print progress to the console""" print_progress = lambda: print( # noqa E731 - f'Progress: {downloader.progress() / 10 ** 6:.2f}MB / {downloader.size / 10 ** 6:.2f}MB' + f"Progress: {downloader.progress() / 10 ** 6:.2f}MB / {downloader.size / 10 ** 6:.2f}MB" ) downloader = Downloader(dirs.url, dirs.download_dest, dirs.hash_url, mode=mode) dl_thread = threading.Thread(target=downloader.download, daemon=True) @@ -197,8 +222,8 @@ def download_ffmpeg(dirs: InstallDirs, mode: str): def decompress(path, destination): - '''Decompresses `path` into `destination`''' - if path.endswith('.zip'): + """Decompresses `path` into `destination`""" + if path.endswith(".zip"): with zipfile.ZipFile(path) as f: f.extractall(destination) else: @@ -207,18 +232,18 @@ def decompress(path, destination): def move_ffmpeg_exe_to_top_level(top_level): - ''' + """ Finds the `bin/ffmpeg.exe` file in a directory tree and moves it to the top-level of that tree. EG: `C:/FFMPEG/ffmpeg-release-essentials/bin/ffmpeg.exe` -> `C:/FFMPEG/bin/ffmpeg.exe`. Args: top_level (str): the tree to search - ''' + """ for root, _, files in os.walk(top_level): for file in files: - if file == 'ffmpeg.exe': - base_path = os.path.abspath(os.path.join(root, '..')) + if file == "ffmpeg.exe": + base_path = os.path.abspath(os.path.join(root, "..")) to_remove = os.listdir(top_level) for item in os.listdir(base_path): @@ -234,89 +259,91 @@ def move_ffmpeg_exe_to_top_level(top_level): def add_path_to_environment(path): - '''Adds a filepath to the users PATH variable after asking the user's consent''' - os_path = os.environ['path'] - if not os_path.endswith(';'): - os_path += ';' + """Adds a filepath to the users PATH variable after asking the user's consent""" + os_path = os.environ["path"] + if not os_path.endswith(";"): + os_path += ";" command = f'[Environment]::SetEnvironmentVariable("Path","{os_path}{path}","User")' - print('\n\n') + print("\n\n") print(command) print() try: - subprocess.check_output(['powershell', command]) + subprocess.check_output(["powershell", command]) except subprocess.CalledProcessError as e: print(e.stdout.decode()) - BUILDS = { # format = { [name]: { [format]: ([gyan name], [github name]) } } - 'release-full': { - '7z': ('release-full', 'full_build'), - 'zip': (None, 'full_build') + "release-full": {"7z": ("release-full", "full_build"), "zip": (None, "full_build")}, + "release-full-shared": { + "7z": ("release-full-shared", "full_build-shared"), + "zip": (None, "full_build-shared"), }, - 'release-full-shared': { - '7z': ('release-full-shared', 'full_build-shared'), - 'zip': (None, 'full_build-shared') + "release-essentials": { + "7z": ("release-essentials", "essentials_build"), + "zip": ("release-essentials", "essentials_build"), }, - 'release-essentials': { - '7z': ('release-essentials', 'essentials_build'), - 'zip': ('release-essentials', 'essentials_build') - }, - 'git-essentials': { - '7z': ('git-essentials', None) - }, - 'git-full': { - '7z': ('git-full', None) - } + "git-essentials": {"7z": ("git-essentials", None)}, + "git-full": {"7z": ("git-full", None)}, } -INSTALL_DIR = 'C:\\' +INSTALL_DIR = "C:\\" -if __name__ == '__main__': +if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( - '--install-dir', type=str, default=INSTALL_DIR, - help=f'The path to install FFMPEG to (default is {INSTALL_DIR})' + "--install-dir", + type=str, + default=INSTALL_DIR, + help=f"The path to install FFMPEG to (default is {INSTALL_DIR})", ) parser.add_argument( - '--build', type=str, - help='The build of FFMPEG to install', + "--build", + type=str, + help="The build of FFMPEG to install", choices=list(BUILDS.keys()), - default='release-full' + default="release-full", ) parser.add_argument( - '--format', choices=('7z', 'zip'), default='zip' if not AVAILABLE_7Z else '7z', - help='Preferred file format' + "--format", + choices=("7z", "zip"), + default="zip" if not AVAILABLE_7Z else "7z", + help="Preferred file format", ) parser.add_argument( - '--overwrite', action='store_true', help='Overwrite existing install', default=False + "--overwrite", + action="store_true", + help="Overwrite existing install", + default=False, ) parser.add_argument( - '--downloader', choices=('default', 'windows', 'wget', 'curl'), default='default', help=( - 'Control how files are downloaded.' + "--downloader", + choices=("default", "windows", "wget", "curl"), + default="default", + help=( + "Control how files are downloaded." ' "default" will use python libraries to download, "windows" will use Invoke-WebRequest,' ' "wget" and "curl" will attempt to use their respective CLI utilities' - ) + ), ) args = parser.parse_args() - dirs = InstallDirs(get_ffmpeg_url( - args.build, args.format), args.install_dir) + dirs = InstallDirs(get_ffmpeg_url(args.build, args.format), args.install_dir) - print(f'Making install dir {dirs.install_path!r}') + print(f"Making install dir {dirs.install_path!r}") make_empty_path(dirs.install_path, overwrite=args.overwrite) - print(f'Downloading {dirs.url!r} to {dirs.download_dest!r}') + print(f"Downloading {dirs.url!r} to {dirs.download_dest!r}") download_ffmpeg(dirs, args.downloader) - print(f'Unzipping {dirs.download_dest!r} to {dirs.unzip_dest!r}') + print(f"Unzipping {dirs.download_dest!r} to {dirs.unzip_dest!r}") decompress(dirs.download_dest, dirs.unzip_dest) - print(f'Move bin/ffmpeg.exe to top level of {dirs.install_path!r}') + print(f"Move bin/ffmpeg.exe to top level of {dirs.install_path!r}") move_ffmpeg_exe_to_top_level(dirs.install_path) - print(f'FFMPEG installed to {dirs.install_path!r}') + print(f"FFMPEG installed to {dirs.install_path!r}") - add_path_to_environment(os.path.abspath(os.path.join(dirs.install_path, 'bin'))) + add_path_to_environment(os.path.abspath(os.path.join(dirs.install_path, "bin"))) diff --git a/setup.py b/setup.py index 57fca11..c2f49e7 100644 --- a/setup.py +++ b/setup.py @@ -64,7 +64,7 @@ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", ], project_urls={ diff --git a/tests/test_framesextractor.py b/tests/test_framesextractor.py index 091ab76..090a197 100644 --- a/tests/test_framesextractor.py +++ b/tests/test_framesextractor.py @@ -15,24 +15,28 @@ def test_all(): video_length = 52.3 interval = 1 ffmpeg_path = None - FramesExtractor(video_path, output_dir, video_length, - interval=interval, ffmpeg_path=ffmpeg_path) + FramesExtractor( + video_path, output_dir, video_length, interval=interval, ffmpeg_path=ffmpeg_path + ) with pytest.raises(FileNotFoundError): video_path = os.path.join(script_path, "thisvideodoesnotexist.mp4") output_dir = create_and_return_temporary_directory() - FramesExtractor(video_path, output_dir, video_length, interval=1, - ffmpeg_path=None) + FramesExtractor( + video_path, output_dir, video_length, interval=1, ffmpeg_path=None + ) with pytest.raises(FFmpegNotFound): video_path = os.path.join(script_path, os.path.pardir, "assets", "rocket.mkv") output_dir = create_and_return_temporary_directory() ffmpeg_path = os.path.join(output_dir, "ffmpeg") - FramesExtractor(video_path, output_dir, video_length, interval=1, - ffmpeg_path=ffmpeg_path) + FramesExtractor( + video_path, output_dir, video_length, interval=1, ffmpeg_path=ffmpeg_path + ) with pytest.raises(FramesExtractorOutPutDirDoesNotExist): video_path = os.path.join(script_path, "../assets/rocket.mkv") output_dir = os.path.join(script_path, "thisdirdoesnotexist/") - FramesExtractor(video_path, output_dir, video_length, interval=1, - ffmpeg_path=None) + FramesExtractor( + video_path, output_dir, video_length, interval=1, ffmpeg_path=None + ) diff --git a/tests/test_videoduration.py b/tests/test_videoduration.py index 7ff7019..9127be9 100644 --- a/tests/test_videoduration.py +++ b/tests/test_videoduration.py @@ -34,4 +34,4 @@ def test_video_duration(): create_and_return_temporary_directory(), ("thisdirdoesnotexist" + os.path.sep), ) - video_duration(url="https://example.com", path=storage_path) \ No newline at end of file + video_duration(url="https://example.com", path=storage_path) diff --git a/tests/test_videohash.py b/tests/test_videohash.py index 85d3b6a..c42cc86 100644 --- a/tests/test_videohash.py +++ b/tests/test_videohash.py @@ -144,5 +144,6 @@ def __init__(self, hash=None): ) VideoHash(path=path) + if __name__ == "__main__": - test_all() \ No newline at end of file + test_all() diff --git a/videohash2/exceptions.py b/videohash2/exceptions.py index 33eda7e..73ed5d8 100644 --- a/videohash2/exceptions.py +++ b/videohash2/exceptions.py @@ -66,3 +66,9 @@ class FFmpegFailedToExtractFrames(FFmpegError): """FFmpeg failed to extract any frame at all. Maybe the input video is damaged or corrupt.""" pass + + +class FFmpegUnableToGetDuration(FFmpegError): + """FFmpeg failed to get the duration. Maybe the input video is damaged or corrupt.""" + + pass diff --git a/videohash2/framesextractor.py b/videohash2/framesextractor.py index 785ddd2..137eb57 100644 --- a/videohash2/framesextractor.py +++ b/videohash2/framesextractor.py @@ -117,7 +117,7 @@ def detect_crop( video_path: Optional[str] = None, frames: int = 3, ffmpeg_path: Optional[str] = None, - video_length: float = 2 + video_length: float = 2, ) -> list: """ Detects the the amount of cropping to remove black bars. @@ -148,7 +148,6 @@ def detect_crop( 7200, 14400, ] - crop_list = [] @@ -162,7 +161,9 @@ def detect_crop( command = f'"{ffmpeg_path}" -ss {start_time} -i "{video_path}" -vframes {frames} -vf cropdetect -f null -' - process = Popen(shlex.split(command), stdin=DEVNULL, stdout=PIPE, stderr=PIPE) + process = Popen( + shlex.split(command), stdin=DEVNULL, stdout=PIPE, stderr=PIPE + ) output, error = process.communicate() @@ -205,8 +206,10 @@ def extract(self) -> None: output_dir = shlex.quote(self.output_dir) crop = FramesExtractor.detect_crop( - video_path=video_path, frames=3, ffmpeg_path=ffmpeg_path, - video_length=video_length + video_path=video_path, + frames=3, + ffmpeg_path=ffmpeg_path, + video_length=video_length, ) command = [ @@ -218,7 +221,7 @@ def extract(self) -> None: "144x144", "-r", str(self.interval), - str(output_dir)+"video_frame_%07d.jpeg", + str(output_dir) + "video_frame_%07d.jpeg", ] process = Popen(command, stdin=DEVNULL, stdout=PIPE, stderr=PIPE) diff --git a/videohash2/utils.py b/videohash2/utils.py index 6cad2a8..c5f8045 100644 --- a/videohash2/utils.py +++ b/videohash2/utils.py @@ -35,6 +35,7 @@ def does_path_exists(path: str) -> bool: # it's file return False + def create_and_return_temporary_directory() -> str: """ create a temporary directory where we can store the video, frames and the @@ -48,6 +49,7 @@ def create_and_return_temporary_directory() -> str: Path(path).mkdir(parents=True, exist_ok=True) return path + def _get_task_uid() -> str: """ Returns an unique task id for the instance. Task id is used to @@ -68,4 +70,4 @@ def _get_task_uid() -> str: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ) for _ in range(20) - ) \ No newline at end of file + ) diff --git a/videohash2/videocopy.py b/videohash2/videocopy.py index 3faaad2..7c6dd08 100644 --- a/videohash2/videocopy.py +++ b/videohash2/videocopy.py @@ -5,18 +5,22 @@ from typing import Optional from .exceptions import DidNotSupplyPathOrUrl, StoragePathDoesNotExist from .downloader import Download -from .utils import (get_list_of_all_files_in_dir, - does_path_exists, - create_and_return_temporary_directory, - _get_task_uid) +from .utils import ( + get_list_of_all_files_in_dir, + does_path_exists, + create_and_return_temporary_directory, + _get_task_uid, +) + def _copy_video_to_video_dir( - video_dir: str, - video_download_dir: str, - do_not_copy: Optional[bool] = True, - download_worst: bool = False, - url: Optional[str] = None, - path: Optional[str] = None) -> str: + video_dir: str, + video_download_dir: str, + do_not_copy: Optional[bool] = True, + download_worst: bool = False, + url: Optional[str] = None, + path: Optional[str] = None, +) -> str: """ Copy the video from the path to the video directory. @@ -51,9 +55,9 @@ def _copy_video_to_video_dir( video_path = os.path.join(video_dir, (f"video.{extension}")) if do_not_copy: - os.symlink(path, video_path) + os.symlink(os.path.abspath(path), video_path) else: - shutil.copyfile(path, video_path) + shutil.copyfile(os.path.abspath(path), video_path) if url: @@ -74,16 +78,17 @@ def _copy_video_to_video_dir( video_path = f"{video_dir}video.{extension}" if do_not_copy: - os.symlink(downloaded_file, video_path) + os.symlink(os.path.abspath(downloaded_file), video_path) else: - shutil.copyfile(downloaded_file, video_path) + shutil.copyfile(os.path.abspath(downloaded_file), video_path) return video_path + def _create_required_dirs_and_check_for_errors( - url: Optional[str] = None, - path: Optional[str] = None, - storage_path: Optional[str] = None + url: Optional[str] = None, + path: Optional[str] = None, + storage_path: Optional[str] = None, ) -> tuple: """ Creates important directories before the main processing starts. @@ -119,22 +124,16 @@ def _create_required_dirs_and_check_for_errors( if not storage_path: storage_path = create_and_return_temporary_directory() if not does_path_exists(storage_path): - raise StoragePathDoesNotExist( - f"Storage path '{storage_path}' does not exist." - ) + raise StoragePathDoesNotExist(f"Storage path '{storage_path}' does not exist.") os_path_sep = os.path.sep - storage_path = os.path.join( - storage_path, (f"{_get_task_uid()}{os_path_sep}") - ) + storage_path = os.path.join(storage_path, (f"{_get_task_uid()}{os_path_sep}")) video_dir = os.path.join(storage_path, (f"video{os_path_sep}")) Path(video_dir).mkdir(parents=True, exist_ok=True) - video_download_dir = os.path.join( - storage_path, (f"downloadedvideo{os_path_sep}") - ) + video_download_dir = os.path.join(storage_path, (f"downloadedvideo{os_path_sep}")) Path(video_download_dir).mkdir(parents=True, exist_ok=True) frames_dir = os.path.join(storage_path, (f"frames{os_path_sep}")) @@ -149,8 +148,14 @@ def _create_required_dirs_and_check_for_errors( horizontally_concatenated_image_dir = os.path.join( storage_path, (f"horizontally_concatenated_image{os_path_sep}") ) - Path(horizontally_concatenated_image_dir).mkdir( - parents=True, exist_ok=True + Path(horizontally_concatenated_image_dir).mkdir(parents=True, exist_ok=True) + + return ( + storage_path, + video_dir, + video_download_dir, + frames_dir, + tiles_dir, + collage_dir, + horizontally_concatenated_image_dir, ) - - return storage_path, video_dir, video_download_dir, frames_dir, tiles_dir, collage_dir, horizontally_concatenated_image_dir \ No newline at end of file diff --git a/videohash2/videoduration.py b/videohash2/videoduration.py index 40cde9a..2dfe35b 100644 --- a/videohash2/videoduration.py +++ b/videohash2/videoduration.py @@ -2,21 +2,23 @@ import shutil from subprocess import PIPE, Popen from typing import Optional -from .exceptions import DidNotSupplyPathOrUrl -from .videocopy import (_create_required_dirs_and_check_for_errors, - _copy_video_to_video_dir) +from .exceptions import DidNotSupplyPathOrUrl, FFmpegUnableToGetDuration +from .videocopy import ( + _create_required_dirs_and_check_for_errors, + _copy_video_to_video_dir, +) # Module to determine the length of video. # The length is found by the FFmpeg, the output of video_duration is in seconds. -def video_duration(url: Optional[str] = None, - path: Optional[str] = None, - storage_path: Optional[str] = None, - do_not_copy: Optional[bool] = True, - ffmpeg_path: Optional[str] = None - ) -> float: - +def video_duration( + url: Optional[str] = None, + path: Optional[str] = None, + storage_path: Optional[str] = None, + do_not_copy: Optional[bool] = True, + ffmpeg_path: Optional[str] = None, +) -> float: """ Retrieve the exact video duration as echoed by the FFmpeg and return the duration in seconds. Maximum duration supported is 999 hours, above @@ -41,7 +43,7 @@ def video_duration(url: Optional[str] = None, raise DidNotSupplyPathOrUrl( "You must specify either a path or an URL of the video." ) - + if path and url: raise ValueError("Specify either a path or an URL and NOT both.") @@ -50,16 +52,15 @@ def video_duration(url: Optional[str] = None, if url: video_dir, video_download_dir = _create_required_dirs_and_check_for_errors( - url=url, - storage_path=storage_path - )[0:2] + url=url, storage_path=storage_path + )[0:2] path = _copy_video_to_video_dir( video_dir, video_download_dir, do_not_copy=do_not_copy, download_worst=True, - url=url + url=url, ) command = f'"{ffmpeg_path}" -i "{path}"' @@ -73,11 +74,13 @@ def video_duration(url: Optional[str] = None, if match: duration_string = match.group(1) + else: + raise FFmpegUnableToGetDuration() hours, minutes, seconds = duration_string.strip().split(":") if url and path: - cutPath = path[:path.find("/temp_storage_dir")] + cutPath = path[: path.find("/temp_storage_dir")] try: shutil.rmtree(cutPath) diff --git a/videohash2/videohash.py b/videohash2/videohash.py index cfacf7e..86c3576 100644 --- a/videohash2/videohash.py +++ b/videohash2/videohash.py @@ -16,10 +16,12 @@ create_and_return_temporary_directory, does_path_exists, get_list_of_all_files_in_dir, - _get_task_uid + _get_task_uid, +) +from .videocopy import ( + _create_required_dirs_and_check_for_errors, + _copy_video_to_video_dir, ) -from .videocopy import (_create_required_dirs_and_check_for_errors, - _copy_video_to_video_dir) from .videoduration import video_duration @@ -79,27 +81,26 @@ def __init__( self.task_uid = _get_task_uid() - (self.storage_path, - self.video_dir, - self.video_download_dir, - self.frames_dir, - self.tiles_dir, - self.collage_dir, - self.horizontally_concatenated_image_dir + ( + self.storage_path, + self.video_dir, + self.video_download_dir, + self.frames_dir, + self.tiles_dir, + self.collage_dir, + self.horizontally_concatenated_image_dir, ) = _create_required_dirs_and_check_for_errors( - url=self.url, - path=self.path, - storage_path=self.storage_path + url=self.url, path=self.path, storage_path=self.storage_path ) self.video_path = _copy_video_to_video_dir( - video_dir=self.video_dir, - video_download_dir=self.video_download_dir, - do_not_copy=self.do_not_copy, - download_worst=self.download_worst, - url=self.url, - path=self.path - ) + video_dir=self.video_dir, + video_download_dir=self.video_download_dir, + do_not_copy=self.do_not_copy, + download_worst=self.download_worst, + url=self.url, + path=self.path, + ) self.video_duration = video_duration(path=self.video_path)