Fixed issues with windows and with existing filenames

This commit is contained in:
Fabrice Quenneville 2020-12-14 00:01:49 -05:00
parent 96594806e0
commit 3ddce45933
8 changed files with 78 additions and 58 deletions

View File

@ -17,7 +17,7 @@ Synopsis
[-filters:fferror,old,lowres,hd,720p,1080p,uhd,mpeg,mpeg4,x264,wmv3,wmv] [-filters:fferror,old,lowres,hd,720p,1080p,uhd,mpeg,mpeg4,x264,wmv3,wmv]
[-out:mkv/mp4,x265/av1] [-out:mkv/mp4,x265/av1]
[-print:list,formated,verbose] [-print:list,formated,verbose]
[-dir/-files:"/mnt/media/",,"/mnt/media2/"] [-dirs/-files:"/mnt/media/",,"/mnt/media2/"]
**for multiple files or filenames use double comma separated values ",,"** **for multiple files or filenames use double comma separated values ",,"**
@ -109,7 +109,7 @@ Select the outputs for the video conversions
* verbose: Print the FFmpeg output during the video conversions * verbose: Print the FFmpeg output during the video conversions
-dir: -dirs:
===== =====
["/mnt/media/",,"/mnt/media2/"] ["/mnt/media/",,"/mnt/media2/"]
@ -128,11 +128,11 @@ Examples
.. code-block:: bash .. code-block:: bash
# List all videos with old codec in formated format # List all videos with old codec in formated format
./curator.py list -filters:old -print:formated -dir:/mnt/media/ >> ../medlist.txt ./curator.py list -filters:old -print:formated -dirs:/mnt/media/ >> ../medlist.txt
# Convert all videos with the codec mpeg4 in a mp4 using the av1 video codec and the delete the originals # Convert all videos with the codec mpeg4 in a mp4 using the av1 video codec and the delete the originals
./curator.py convert -del -filters:mpeg4 -out:av1,mp4 -dir:"/mnt/media/Movies/" ./curator.py convert -del -filters:mpeg4 -out:av1,mp4 -dirs:"/mnt/media/Movies/"
# Convert any video with avi or mpg extensions, print formated text including ffmpeg's output and then delete the originals # Convert any video with avi or mpg extensions, print formated text including ffmpeg's output and then delete the originals
./curator.py convert -del -in:avi,mpg -print:formated,verbose -dir:/mnt/media/ ./curator.py convert -del -in:avi,mpg -print:formated,verbose -dirs:/mnt/media/
More examples in :doc:`use_cases` More examples in :doc:`use_cases`

View File

@ -9,7 +9,7 @@ Quickstart
[-filters:fferror,old,lowres,hd,720p,1080p,uhd,mpeg,mpeg4,x264,wmv3,wmv] [-filters:fferror,old,lowres,hd,720p,1080p,uhd,mpeg,mpeg4,x264,wmv3,wmv]
[-out:mkv/mp4,x265/av1] [-out:mkv/mp4,x265/av1]
[-print:list,formated,verbose] [-print:list,formated,verbose]
[-dir/-files:"/mnt/media/",,"/mnt/media2/"] [-dirs/-files:"/mnt/media/",,"/mnt/media2/"]
**for multiple files or filenames use double comma separated values ",,"** **for multiple files or filenames use double comma separated values ",,"**
@ -27,10 +27,10 @@ Examples:
.. code-block:: bash .. code-block:: bash
# List all videos with old codec in formated format # List all videos with old codec in formated format
./curator.py list -filters:old -print:formated -dir:/mnt/media/ >> ../medlist.txt ./curator.py list -filters:old -print:formated -dirs:/mnt/media/ >> ../medlist.txt
# Convert all videos with the codec mpeg4 in a mp4 using the av1 video codec and the delete the originals # Convert all videos with the codec mpeg4 in a mp4 using the av1 video codec and the delete the originals
./curator.py convert -del -filters:mpeg4 -out:av1,mp4 -dir:"/mnt/media/Movies/" ./curator.py convert -del -filters:mpeg4 -out:av1,mp4 -dirs:"/mnt/media/Movies/"
# Convert any video with avi or mpg extensions, print formated text including ffmpeg's output and then delete the originals # Convert any video with avi or mpg extensions, print formated text including ffmpeg's output and then delete the originals
./curator.py convert -del -in:avi,mpg -print:formated,verbose -dir:/mnt/media/ ./curator.py convert -del -in:avi,mpg -print:formated,verbose -dirs:/mnt/media/
More examples in :doc:`use_cases` More examples in :doc:`use_cases`

View File

@ -21,13 +21,13 @@ List all videos with old codec in formated format
.. code-block:: bash .. code-block:: bash
./curator.py list -filters:old -dir:/mnt/media/ ./curator.py list -filters:old -dirs:/mnt/media/
List all videos with substandard definitions with a formated output List all videos with substandard definitions with a formated output
.. code-block:: bash .. code-block:: bash
./curator.py list -filters:subsd -print:formated -dir:/mnt/media/ ./curator.py list -filters:subsd -print:formated -dirs:/mnt/media/
.. _purge: .. _purge:
@ -41,19 +41,19 @@ List and delete all videos using the `Windows Media Video <https://en.wikipedia.
.. code-block:: bash .. code-block:: bash
./curator.py list -del -filters:wmv -dir:/mnt/media/ ./curator.py list -del -filters:wmv -dirs:/mnt/media/
List and delete all videos using an `Audio Video Interleave <https://en.wikipedia.org/wiki/Audio_Video_Interleave>`_ List and delete all videos using an `Audio Video Interleave <https://en.wikipedia.org/wiki/Audio_Video_Interleave>`_
.. code-block:: bash .. code-block:: bash
./curator.py list -del -in:avi -dir:/mnt/media/ ./curator.py list -del -in:avi -dirs:/mnt/media/
List and delete any videos with encoding errors List and delete any videos with encoding errors
.. code-block:: bash .. code-block:: bash
./curator.py list -del -filters:fferror -dir:/mnt/media/ ./curator.py list -del -filters:fferror -dirs:/mnt/media/
@ -66,19 +66,19 @@ List all videos with encoding errors
.. code-block:: bash .. code-block:: bash
./curator.py list -filters:fferror -dir:/mnt/media/ ./curator.py list -filters:fferror -dirs:/mnt/media/
List and delete any videos with encoding errors List and delete any videos with encoding errors
.. code-block:: bash .. code-block:: bash
./curator.py list -del -filters:fferror -dir:/mnt/media/ ./curator.py list -del -filters:fferror -dirs:/mnt/media/
Convert all videos with encoding errors to `High Efficiency Video Coding <https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding>`_ and the delete the originals Convert all videos with encoding errors to `High Efficiency Video Coding <https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding>`_ and the delete the originals
.. code-block:: bash .. code-block:: bash
./curator.py convert -del -filters:fferror -dir:"/mnt/media/Movies/" ./curator.py convert -del -filters:fferror -dirs:"/mnt/media/Movies/"
.. _convert: .. _convert:
@ -90,16 +90,16 @@ Convert all videos with old codecs to `High Efficiency Video Coding <https://en.
.. code-block:: bash .. code-block:: bash
./curator.py convert -del -filters:old -dir:"/mnt/media/Movies/" ./curator.py convert -del -filters:old -dirs:"/mnt/media/Movies/"
Convert all videos with the codec mpeg4 to an mkv container using the av1 video codec Convert all videos with the codec mpeg4 to an mkv container using the av1 video codec
.. code-block:: bash .. code-block:: bash
./curator.py convert -filters:mpeg4 -out:av1,mkv -dir:"/mnt/media/Movies/" ./curator.py convert -filters:mpeg4 -out:av1,mkv -dirs:"/mnt/media/Movies/"
Convert any video with avi or mpg extensions, print formated text including ffmpeg's output and then delete the originals Convert any video with avi or mpg extensions, print formated text including ffmpeg's output and then delete the originals
.. code-block:: bash .. code-block:: bash
./curator.py convert -del -in:avi,mpg -print:formated,verbose -dir:/mnt/media/ ./curator.py convert -del -in:avi,mpg -print:formated,verbose -dirs:/mnt/media/

View File

@ -10,13 +10,13 @@ To delete all non-hd videos in a folder:
.. code-block:: bash .. code-block:: bash
./curator.py list -del -filters:lowres -dir/-files:"/mnt/media/" ./curator.py list -del -filters:lowres -dirs/-files:"/mnt/media/"
To delete all substandard videos in a folder: To delete all substandard videos in a folder:
.. code-block:: bash .. code-block:: bash
./curator.py list -del -filters:subsd -dir/-files:"/mnt/media/" ./curator.py list -del -filters:subsd -dirs/-files:"/mnt/media/"
.. image:: ../_static/Screenshot-delete.png .. image:: ../_static/Screenshot-delete.png
:width: 600 :width: 600
@ -26,19 +26,19 @@ To delete all videos in a folder with encoding errors:
.. code-block:: bash .. code-block:: bash
./curator.py list -del -filters:fferror -dir/-files:"/mnt/media/" ./curator.py list -del -filters:fferror -dirs/-files:"/mnt/media/"
To convert (repair) then delete all videos in a folder with encoding errors: To convert (repair) then delete all videos in a folder with encoding errors:
.. code-block:: bash .. code-block:: bash
./curator.py convert -del -filters:fferror -dir/-files:"/mnt/media/" ./curator.py convert -del -filters:fferror -dirs/-files:"/mnt/media/"
To delete all videos in a folder: To delete all videos in a folder:
.. code-block:: bash .. code-block:: bash
./curator.py list -del -filters:lowres -dir/-files:"/mnt/media/" ./curator.py list -del -filters:lowres -dirs/-files:"/mnt/media/"
All these commands can have valuable use but are irrecoverable if done unintended. All these commands can have valuable use but are irrecoverable if done unintended.

View File

@ -4,9 +4,9 @@
* List all the video's and their codecs with or without filters * List all the video's and their codecs with or without filters
* Batch recode videos to more modern codecs (x265 / AV1) based on filters: extentions, codecs ... * Batch recode videos to more modern codecs (x265 / AV1) based on filters: extentions, codecs ...
ex: ex:
./converter.py list -in:any -filters:old -dir:/mnt/media/ >> ../medlist.txt ./converter.py list -in:any -filters:old -dirs:/mnt/media/ >> ../medlist.txt
./converter.py convert -del -in:any -filters:mpeg4 -out:x265,mkv -dir:"/mnt/media/Movies/" ./converter.py convert -del -in:any -filters:mpeg4 -out:x265,mkv -dirs:"/mnt/media/Movies/"
./converter.py convert -del -in:avi,mpg -dir:/mnt/media/ ./converter.py convert -del -in:avi,mpg -dirs:/mnt/media/
''' '''
import sys import sys
@ -25,14 +25,14 @@ def main():
# confirm that the command has enough parameters # confirm that the command has enough parameters
if len(sys.argv) < 2: if len(sys.argv) < 2:
print(f"{colorama.Fore.RED}ERROR: Command not understood, please see documentation.{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}ERROR: Command not understood, please see documentation.{colorama.Fore.RESET}")
# confirm that ffmpeg in indeed installed # confirm that ffmpeg in indeed installed
ffmpeg_version = detect_ffmpeg() ffmpeg_version = detect_ffmpeg()
if not ffmpeg_version: if not ffmpeg_version:
print(f"{colorama.Fore.RED}No ffmpeg version detected{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}No ffmpeg version detected{colorama.Fore.RESET}")
exit() exit()
print(f"{colorama.Fore.BLUE}ffmpeg version detected: {ffmpeg_version}{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.BLUE}ffmpeg version detected: {ffmpeg_version}{colorama.Fore.RESET}")
# Get/load command parameters # Get/load command parameters
directories = [] directories = []
@ -45,9 +45,9 @@ def main():
for arg in sys.argv: for arg in sys.argv:
# Confirm with the user that he selected to delete found files # Confirm with the user that he selected to delete found files
if "-del" in arg: if "-del" in arg:
print(f"{colorama.Fore.YELLOW}WARNING: Delete option selected!{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.YELLOW}WARNING: Delete option selected!{colorama.Fore.RESET}")
if not user_confirm(f"Are you sure you wish to delete all found results after selected operations are succesfull ? [Y/N] ?", color="yellow"): if not user_confirm(f"Are you sure you wish to delete all found results after selected operations are succesfull ? [Y/N] ?", color="yellow"):
print(f"{colorama.Fore.GREEN}Exiting!{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.GREEN}Exiting!{colorama.Fore.RESET}")
exit() exit()
elif "-in:" in arg: elif "-in:" in arg:
inputs += arg[4:].split(",") inputs += arg[4:].split(",")
@ -59,8 +59,8 @@ def main():
printop += arg[7:].split(",") printop += arg[7:].split(",")
elif "-files:" in arg: elif "-files:" in arg:
files += arg[7:].split(",,") files += arg[7:].split(",,")
elif "-dir:" in arg: elif "-dirs:" in arg:
directories += arg[5:].split(",,") directories += arg[6:].split(",,")
# Loading the media library # Loading the media library
if len(files) > 0: if len(files) > 0:
@ -68,7 +68,8 @@ def main():
elif len(directories) > 0: elif len(directories) > 0:
medialibrary = MediaLibrary(directories = directories, inputs = inputs, filters = filters) medialibrary = MediaLibrary(directories = directories, inputs = inputs, filters = filters)
else: else:
print(f"{colorama.Fore.RED}ERROR: No files or directories selected.{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}ERROR: No files or directories selected.{colorama.Fore.RESET}")
return
# Actions # Actions
@ -82,12 +83,12 @@ def main():
if medialibrary.videos[filepath].useful: if medialibrary.videos[filepath].useful:
if "formated" in printop or "verbose" in printop: if "formated" in printop or "verbose" in printop:
if medialibrary.videos[filepath].error: if medialibrary.videos[filepath].error:
print(f"{colorama.Fore.RED}{medialibrary.videos[filepath].fprint()}{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}{medialibrary.videos[filepath].fprint()}{colorama.Fore.RESET}")
else: else:
print(medialibrary.videos[filepath].fprint()) print(medialibrary.videos[filepath].fprint())
else: else:
if medialibrary.videos[filepath].error: if medialibrary.videos[filepath].error:
print(f"{colorama.Fore.RED}{medialibrary.videos[filepath]}{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}{medialibrary.videos[filepath]}{colorama.Fore.RESET}")
else: else:
print(medialibrary.videos[filepath]) print(medialibrary.videos[filepath])
@ -104,12 +105,12 @@ def main():
if medialibrary.videos[filepath].useful: if medialibrary.videos[filepath].useful:
if "formated" in printop or "verbose" in printop: if "formated" in printop or "verbose" in printop:
if medialibrary.videos[filepath].error: if medialibrary.videos[filepath].error:
print(f"{colorama.Fore.RED}{medialibrary.videos[filepath].fprint()}{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}{medialibrary.videos[filepath].fprint()}{colorama.Fore.RESET}")
else: else:
print(medialibrary.videos[filepath].fprint()) print(medialibrary.videos[filepath].fprint())
else: else:
if medialibrary.videos[filepath].error: if medialibrary.videos[filepath].error:
print(f"{colorama.Fore.RED}{medialibrary.videos[filepath]}{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}{medialibrary.videos[filepath]}{colorama.Fore.RESET}")
else: else:
print(medialibrary.videos[filepath]) print(medialibrary.videos[filepath])
@ -133,14 +134,14 @@ def main():
vcodec = "x265" vcodec = "x265"
# Verbosing # Verbosing
print(f"{colorama.Fore.GREEN}****** Starting conversion {counter} of {len(keylist)}: '{colorama.Fore.CYAN}{medialibrary.videos[filepath].filename_origin}{colorama.Fore.GREEN}' from {colorama.Fore.CYAN}{medialibrary.videos[filepath].codec}{colorama.Fore.GREEN} to {colorama.Fore.CYAN}{vcodec}{colorama.Fore.GREEN}...{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.GREEN}****** Starting conversion {counter} of {len(keylist)}: '{colorama.Fore.CYAN}{medialibrary.videos[filepath].filename_origin}{colorama.Fore.GREEN}' from {colorama.Fore.CYAN}{medialibrary.videos[filepath].codec}{colorama.Fore.GREEN} to {colorama.Fore.CYAN}{vcodec}{colorama.Fore.GREEN}...{colorama.Fore.RESET}")
print(f"{colorama.Fore.CYAN}Original file:{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.CYAN}Original file:{colorama.Fore.RESET}")
if "formated" in printop or "verbose" in printop: if "formated" in printop or "verbose" in printop:
print(medialibrary.videos[filepath].fprint()) print(medialibrary.videos[filepath].fprint())
else: else:
print(medialibrary.videos[filepath]) print(medialibrary.videos[filepath])
print(f"{colorama.Fore.GREEN}Converting please wait...{colorama.Style.RESET_ALL}", end="\r") print(f"{colorama.Fore.GREEN}Converting please wait...{colorama.Fore.RESET}", end="\r")
# Converting # Converting
if medialibrary.videos[filepath].convert(verbose = "verbose" in printop): if medialibrary.videos[filepath].convert(verbose = "verbose" in printop):
@ -153,17 +154,17 @@ def main():
medialibrary.videos[newfpath] = Video(newfpath, verbose = "verbose" in printop) medialibrary.videos[newfpath] = Video(newfpath, verbose = "verbose" in printop)
# Verbose # Verbose
print(f"{colorama.Fore.GREEN}Successfully converted '{medialibrary.videos[filepath].filename_origin}'{colorama.Fore.CYAN}({medialibrary.videos[filepath].filesize}mb){colorama.Fore.GREEN} to '{medialibrary.videos[newfpath].filename_origin}'{colorama.Fore.CYAN}({medialibrary.videos[newfpath].filesize}mb){colorama.Fore.GREEN}, {colorama.Fore.CYAN}new file:{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.GREEN}Successfully converted '{medialibrary.videos[filepath].filename_origin}'{colorama.Fore.CYAN}({medialibrary.videos[filepath].filesize}mb){colorama.Fore.GREEN} to '{medialibrary.videos[newfpath].filename_origin}'{colorama.Fore.CYAN}({medialibrary.videos[newfpath].filesize}mb){colorama.Fore.GREEN}, {colorama.Fore.CYAN}new file:{colorama.Fore.RESET}")
if "formated" in printop or "verbose" in printop: if "formated" in printop or "verbose" in printop:
if medialibrary.videos[newfpath].error: if medialibrary.videos[newfpath].error:
print(f"{colorama.Fore.RED}{medialibrary.videos[newfpath].fprint()}{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}{medialibrary.videos[newfpath].fprint()}{colorama.Fore.RESET}")
else: else:
print(medialibrary.videos[newfpath].fprint()) print(medialibrary.videos[newfpath].fprint())
else: else:
if medialibrary.videos[newfpath].error: if medialibrary.videos[newfpath].error:
print(f"{colorama.Fore.RED}{medialibrary.videos[newfpath]}{colorama.Style.RESET_ALL}") print(f"{colorama.Fore.RED}{medialibrary.videos[newfpath]}{colorama.Fore.RESET}")
else: else:
print(medialibrary.videos[newfpath]) print(medialibrary.videos[newfpath])

View File

@ -25,7 +25,7 @@ def user_confirm(question, color=False):
'''Returns the user answer to a yes or no question''' '''Returns the user answer to a yes or no question'''
if color == "yellow": if color == "yellow":
print(colorama.Fore.YELLOW, end = '') print(colorama.Fore.YELLOW, end = '')
answer = input(question) answer = input(f"{question} ")
print(colorama.Fore.RESET) print(colorama.Fore.RESET)
else: else:
answer = input(question) answer = input(question)
@ -45,4 +45,23 @@ def deletefile(filename):
return False return False
print(f"{colorama.Fore.GREEN}Successfully deleted {filename}{colorama.Fore.RESET}") print(f"{colorama.Fore.GREEN}Successfully deleted {filename}{colorama.Fore.RESET}")
return True return True
def findfreename(filepath, attempt = 0):
'''Delete a file, Returns a boolean'''
attempt += 1
filename = str(filepath)[:str(filepath).rindex(".")]
extension = str(filepath)[str(filepath).rindex("."):]
hevcpath = filename + "[HEVC]" + extension
copynumpath = filename + f"[HEVC]({attempt})" + extension
if not os.path.exists(filepath):
return filepath
elif not os.path.exists(hevcpath):
return hevcpath
elif not os.path.exists(copynumpath):
return copynumpath
return findfreename(filepath, attempt)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
'''Its a video!''' '''Its a video!'''
from .tools import deletefile from .tools import deletefile, findfreename
import subprocess import subprocess
import os import os
import sys import sys
@ -138,12 +138,14 @@ class Video():
# Setting new filename # Setting new filename
if "mp4" in extension: if "mp4" in extension:
newfilename = self.filename_origin[:-4] + ".mp4" newfilename = self.filename_origin[:-4] + ".mp4"
if self.filename_origin == newfilename: if os.path.exists(self.path + newfilename):
newfilename = self.filename_origin[:-4] + "[HEVC]" + ".mp4" newfilename = findfreename(self.path + newfilename)
else: else:
newfilename = self.filename_origin[:-4] + ".mkv" newfilename = self.filename_origin[:-4] + ".mkv"
if self.filename_origin == newfilename: if os.path.exists(self.path + newfilename):
newfilename = self.filename_origin[:-4] + "[HEVC]" + ".mkv" newfilename = findfreename(self.path + newfilename)
print(newfilename)
exit()
self.filename_tmp = newfilename self.filename_tmp = newfilename
@ -159,8 +161,6 @@ class Video():
args += ['-max_muxing_queue_size', '1000'] args += ['-max_muxing_queue_size', '1000']
# conversion output # conversion output
args += [self.path + self.filename_tmp] args += [self.path + self.filename_tmp]
try: try:
if verbose: if verbose:
@ -173,12 +173,13 @@ class Video():
print(f"{colorama.Fore.RED}Conversion failed {e}{colorama.Fore.RESET}") print(f"{colorama.Fore.RED}Conversion failed {e}{colorama.Fore.RESET}")
return False return False
except KeyboardInterrupt: except KeyboardInterrupt:
print(f"{colorama.Style.YELLOW}Conversion cancelled, cleaning up...{colorama.Fore.RESET}") print(f"{colorama.Fore.YELLOW}Conversion cancelled, cleaning up...{colorama.Fore.RESET}")
deletefile(self.path + self.filename_tmp) deletefile(self.path + self.filename_tmp)
self.filename_tmp = "" self.filename_tmp = ""
exit() exit()
else: else:
subprocess.call(['chmod', '777', self.path + self.filename_tmp]) print(self.path + self.filename_tmp)
os.chmod(self.path + self.filename_tmp, 777)
self.filename_new = self.filename_tmp self.filename_new = self.filename_tmp
self.filename_tmp = "" self.filename_tmp = ""
return True return True

View File

@ -1,3 +1,2 @@
pathlib pathlib
colorama colorama
sphinx