Created
September 12, 2022 08:50
-
-
Save BioGeek/4f79528e0ee69ef6cac8f2aa7c05bb56 to your computer and use it in GitHub Desktop.
Code review of FileOps code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "94c12cc8", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Requirement already satisfied: moviepy in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (1.0.3)\n", | |
"Requirement already satisfied: pillow in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (8.4.0)\n", | |
"Requirement already satisfied: decorator<5.0,>=4.0.2 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from moviepy) (4.4.2)\n", | |
"Requirement already satisfied: proglog<=1.0.0 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from moviepy) (0.1.10)\n", | |
"Requirement already satisfied: numpy>=1.17.3 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from moviepy) (1.21.6)\n", | |
"Requirement already satisfied: imageio<3.0,>=2.5 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from moviepy) (2.21.2)\n", | |
"Requirement already satisfied: imageio-ffmpeg>=0.2.0 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from moviepy) (0.4.7)\n", | |
"Requirement already satisfied: tqdm<5.0,>=4.11.2 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from moviepy) (4.60.0)\n", | |
"Requirement already satisfied: requests<3.0,>=2.8.1 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from moviepy) (2.28.1)\n", | |
"Requirement already satisfied: idna<4,>=2.5 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from requests<3.0,>=2.8.1->moviepy) (3.3)\n", | |
"Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from requests<3.0,>=2.8.1->moviepy) (1.26.11)\n", | |
"Requirement already satisfied: charset-normalizer<3,>=2 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from requests<3.0,>=2.8.1->moviepy) (2.1.0)\n", | |
"Requirement already satisfied: certifi>=2017.4.17 in /home/j.vangoey/micromamba/envs/dcr/lib/python3.7/site-packages (from requests<3.0,>=2.8.1->moviepy) (2022.6.15)\n" | |
] | |
} | |
], | |
"source": [ | |
"!pip install moviepy pillow" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"id": "c72e4174", | |
"metadata": { | |
"notebookRunGroups": { | |
"groupValue": "1" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"import os, sys\n", | |
"from pathlib import Path # , PurePath\n", | |
"from shutil import copy2\n", | |
"from typing import Any, Callable, Optional\n", | |
"\n", | |
"import moviepy.video.io.ImageSequenceClip \n", | |
"# Better:\n", | |
"# from moviepy.video.io.ImageSequenceClip import ImageSequenceClip\n", | |
"# and then later use:\n", | |
"# video = ImageSequenceClip(image_files, fps = fps)\n", | |
"# instead of:\n", | |
"# video = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(image_files, fps = fps)\n", | |
"\n", | |
"import moviepy.editor as ed\n", | |
"from PIL import Image, ImageFile" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"id": "0cb28644", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# Mismatch between docstring and function. \n", | |
"# * There is no argument `hex_num`, only `num`\n", | |
"# * `num` is a bad argument name because it is not a number but a filename 'D7E.jpg'\n", | |
"# * the function doesn't return a new filename but an integer\n", | |
"\n", | |
"# Personal preference: use f-strings instead of string concatenation\n", | |
"# so:\n", | |
"# f'0x{num}'\n", | |
"# instead of:\n", | |
"# '0x' + num \n", | |
"\n", | |
"def num_to_base_10(num: str, base: int) -> int:\n", | |
" \"\"\"\n", | |
" Using int() to convert a number in hexadecimal notation to decimal notation\n", | |
"\n", | |
" Args:\n", | |
" `hex_num`: File with name in hexadecimal format, e.g. 'D7E.jpg'\n", | |
"\n", | |
" Returns:\n", | |
" `new_filename`: File with name converted to decimal, e.g. '3454.jpg'\n", | |
" \"\"\"\n", | |
" \n", | |
" if base == 16 and not num.startswith(('0x', '0X')): num = '0x' + num \n", | |
" \n", | |
" dec_num = int(num, base)\n", | |
"\n", | |
" return dec_num" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"id": "25b0002e", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "ValueError", | |
"evalue": "invalid literal for int() with base 16: '0xD7E.jpg'", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m/tmp/ipykernel_168529/2227153845.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# The function doesn't do what the docstring says:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mnum_to_base_10\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'D7E.jpg'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m16\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m/tmp/ipykernel_168529/4202996927.py\u001b[0m in \u001b[0;36mnum_to_base_10\u001b[0;34m(num, base)\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mbase\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m16\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mnum\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstartswith\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'0x'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'0X'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mnum\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'0x'\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mnum\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 25\u001b[0;31m \u001b[0mdec_num\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbase\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 26\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdec_num\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 16: '0xD7E.jpg'" | |
] | |
} | |
], | |
"source": [ | |
"# The function doesn't do what the docstring says:\n", | |
"num_to_base_10('D7E.jpg', 16)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"id": "970f5153", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"3454" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# `dex` should be `dec`\n", | |
"\n", | |
"hex_to_dex = lambda num : str(num_to_base_10(num, base = 16))\n", | |
"\n", | |
"# only use lambda's for anonymous functions (for example in a list comprehension where you don't want\n", | |
"# to explicitly create a new function). Don't assing a lambda function to a variable. Better is to either:\n", | |
"# 1) adapt the original function to have a deafult value of 16 for base\n", | |
"# def num_to_base_10(num: str, base: int = 16) -> str: ...\n", | |
"# or 2) use functools.partial:\n", | |
"\n", | |
"from functools import partial\n", | |
"hex_to_dec = partial(num_to_base_10, base=16)\n", | |
"hex_to_dec('D7E')\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"id": "e22beb17", | |
"metadata": { | |
"notebookRunGroups": { | |
"groupValue": "1" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# Personal preference: use f-strings instead of string concatenation\n", | |
"# so:\n", | |
"# f\"{file_path.parent.name}_{file_path.name}\"\n", | |
"# instead of:\n", | |
"# file_path.parent.name + '_' + file_path.name\n", | |
"\n", | |
"def up_x_folders(file_path: Path, x: int) -> Path:\n", | |
" file_path = file_path.parents[x-1].with_name(file_path.parent.name + '_' + file_path.name)\n", | |
" return file_path" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"id": "b4e2e948", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "ValueError", | |
"evalue": "PosixPath('/') has an empty name", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m/tmp/ipykernel_168529/2114019309.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# There is no error handling for when x is too large\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mup_x_folders\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mPath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcwd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m/tmp/ipykernel_168529/3251594310.py\u001b[0m in \u001b[0;36mup_x_folders\u001b[0;34m(file_path, x)\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mup_x_folders\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile_path\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mPath\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0mPath\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mfile_path\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfile_path\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparents\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwith_name\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile_path\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m'_'\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mfile_path\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 9\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mfile_path\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~/micromamba/envs/dcr/lib/python3.7/pathlib.py\u001b[0m in \u001b[0;36mwith_name\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m 841\u001b[0m \u001b[0;34m\"\"\"Return a new path with the file name changed.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 842\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 843\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"%r has an empty name\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 844\u001b[0m \u001b[0mdrv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mroot\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparts\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_flavour\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparse_parts\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 845\u001b[0m if (not name or name[-1] in [self._flavour.sep, self._flavour.altsep]\n", | |
"\u001b[0;31mValueError\u001b[0m: PosixPath('/') has an empty name" | |
] | |
} | |
], | |
"source": [ | |
"# There is no error handling for when x is too large\n", | |
"up_x_folders(Path.cwd(), 3)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"up_one_folder = lambda file_path : up_x_folders(file_path, x = 1)\n", | |
"\n", | |
"# only use lambda's for anonymous functions (for example in a list comprehension where you don't want\n", | |
"# to explicitly create a new function). Don't assing a lambda function to a variable. Better is to either:\n", | |
"# 1) adapt the original function to have a deafult value of 16 for base\n", | |
"# def up_x_folders(file_path: Path, x: int = 1) -> Path:\n", | |
"# or 2) use functools.partial:\n", | |
"# up_one_folder = partial(up_x_folders, x=1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"id": "80543845", | |
"metadata": { | |
"notebookRunGroups": { | |
"groupValue": "1" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# The code below works but is a complicated design\n", | |
"# Why not for exampe a base class that does the\n", | |
"# part in your _call__ (generic checking of folders exist)\n", | |
"# and derived classes for renaming the files?\n", | |
"\n", | |
"\n", | |
"class FileOps(object):\n", | |
" \"\"\"\n", | |
" Convert filenames by calling an object after assigning a function\n", | |
" to the object to modify the filename in the constructor function.\n", | |
" \"\"\"\n", | |
" def __init__(self, function: Optional[Callable[[Path], Path]] = None) -> None:\n", | |
" \"\"\"\n", | |
" Assign a function to this object that can modify filenames.\n", | |
"\n", | |
" Args:\n", | |
" `function`: Function to modify the filenames, optional.\n", | |
" \"\"\"\n", | |
" self.mod_func = function if function is not None else lambda x : x\n", | |
"\n", | |
" def modify(self, file_path: Path) -> Path:\n", | |
" \"\"\"\n", | |
" Convert filenames by calling an object after assigning a function\n", | |
" to modify the filename in the constructor function.\n", | |
"\n", | |
" Args:\n", | |
" Path to the file that needs to be renamed\n", | |
" Returns:\n", | |
" Path pointing to the file with the modified filename\n", | |
" \"\"\"\n", | |
" # stem = file_path.stem\n", | |
" # suffix = file_path.suffix\n", | |
" \n", | |
" # new_stem = self.mod_func(stem)\n", | |
" # new_suffix = suffix\n", | |
" \n", | |
" # new_name = file_path.with_stem(new_stem).with_suffix(new_suffix)\n", | |
" \n", | |
" new_name = self.mod_func(file_path)\n", | |
" \n", | |
" return new_name\n", | |
" \n", | |
" def write(self, file_path: Path, new_name: Path, target_path: Optional[Path] = None) -> str:\n", | |
" \"\"\"\n", | |
" Write the specified file to the specified target directory\n", | |
" \n", | |
" Args:\n", | |
" `file`: Path to the file we want to rename\n", | |
" `target_path`: Path to the directory where we will write the renamed files\n", | |
" \n", | |
" Returns:\n", | |
" Prints the old filename and the result of the filename conversion\n", | |
" \"\"\"\n", | |
" if not file_path.resolve().is_file(): # Raise exception if the file doesn't exist\n", | |
" raise Exception(f'No file called {file_path}!')\n", | |
" else: file_path = file_path.resolve()\n", | |
"\n", | |
" if target_path is not None: # ! No target: Copy\n", | |
" target_path.mkdir(exist_ok=True) # Create directory if needed\n", | |
" new_path = target_path.resolve() / new_name.name\n", | |
" # print(new_path)\n", | |
" copy2(file_path, new_path)\n", | |
" \n", | |
" else: # ! Else: Rename\n", | |
" new_path = file_path.with_name(new_name.name).resolve()\n", | |
" # print(new_path)\n", | |
" file_path.rename(new_path)\n", | |
" \n", | |
" return f'Renamed file called \"{file_path.name}\" to \"{new_name.name}\".'\n", | |
" \n", | |
" def __call__(self, source: Path, target: Optional[Path] = None) -> None:\n", | |
" \"\"\"\n", | |
" Rename all files in the parent directory and all sub directories.\n", | |
"\n", | |
" Args:\n", | |
" `source`: Path object pointing to the chosen parent directory\n", | |
" `target`: Path object pointing to the desired target directory\n", | |
"\n", | |
" Returns:\n", | |
" Prints the number of filenames converted to hexadecimal notation\n", | |
" \"\"\"\n", | |
" \n", | |
" if not source.resolve().exists(): # Raise exception if the directory doesn't exist\n", | |
" raise Exception(f'No directory called {source}!')\n", | |
"\n", | |
" else:\n", | |
" self.source_path = source.resolve()\n", | |
" print(f'Reading source files from :{self.source_path}.')\n", | |
"\n", | |
" if target is not None: # ! No target: Copy\n", | |
" target.mkdir(exist_ok=True) # Create directory if needed\n", | |
" self.target_path = target.resolve()\n", | |
" print(f'Writing renamed files to :{self.target_path}.')\n", | |
" \n", | |
" else: # ! Else: Rename\n", | |
" self.target_path = None\n", | |
" \n", | |
" self.count = 0\n", | |
" \n", | |
" for path in self.source_path.glob('**/*'):\n", | |
" if path.is_file():\n", | |
" new_name = self.modify(path)\n", | |
" self.write(path, new_name, self.target_path)\n", | |
" self.count += 1\n", | |
"\n", | |
" if self.count: print(f'Succesfully renamed {self.count} files.')\n", | |
" else: raise UnboundLocalError('No files found to rename.')\n", | |
" \n", | |
" def img_to_vid(self, video_name: str, video_path: Path, fps: int = 24):\n", | |
" \"\"\"\n", | |
" Converts images to video\n", | |
"\n", | |
" Args:\n", | |
" `video_name`: Chosen video name\n", | |
" `video_path`: Path to the video\n", | |
" `fps`: Desired framerate for the video. Defaults to 24.\n", | |
" \"\"\"\n", | |
" print(f'Converting {self.count} images to a video with {fps} fps',\n", | |
" f'called \"{video_name}\",\\n saving to: {video_path} when finished.')\n", | |
"\n", | |
" img = ['.jpg', '.png', '.jpeg']\n", | |
" img_path = self.target_path if self.target_path else self.source_path\n", | |
" image_files = [str(p) for p in img_path.iterdir() if p.suffix in img]\n", | |
" \n", | |
" ImageFile.LOAD_TRUNCATED_IMAGES = True\n", | |
"\n", | |
" video = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(image_files, fps = fps)\n", | |
" video_path.mkdir(exist_ok=True) # Create directory if needed\n", | |
" video_path = Path(video_path / video_name).with_suffix('.mp4')\n", | |
" video.write_videofile(str(video_path), codec = 'mpeg4')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"id": "bf153f65", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"source_dir = Path('OriginalFiles').resolve()\n", | |
"target_dir = Path('RenamedFiles').resolve() # ! specify to copy, omit to rename" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "08916c28", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"no_op = FileOps()\n", | |
"no_op(source_dir, target_dir)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"id": "a5f022dd", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Reading source files from :/home/j.vangoey/Downloads/OriginalFiles.\n", | |
"Writing renamed files to :/home/j.vangoey/Downloads/RenamedFiles.\n", | |
"Succesfully renamed 24 files.\n" | |
] | |
} | |
], | |
"source": [ | |
"batch_up_one_folder = FileOps(up_one_folder)\n", | |
"batch_up_one_folder(source_dir, target_dir)\n", | |
"\n", | |
"# batch_rename_to_dec = FileOps(hex_to_dex)\n", | |
"# batch_rename_to_dec(source_dir, target_dir)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"id": "66d27956", | |
"metadata": { | |
"notebookRunGroups": { | |
"groupValue": "2" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Converting 24 images to a video with 24 fps called \"VideoFromImages\",\n", | |
" saving to: /home/j.vangoey/Downloads/RenamedFiles/Video when finished.\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"t: 33%|███▎ | 8/24 [00:00<00:00, 76.47it/s, now=None]" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Moviepy - Building video /home/j.vangoey/Downloads/RenamedFiles/Video/VideoFromImages.mp4.\n", | |
"Moviepy - Writing video /home/j.vangoey/Downloads/RenamedFiles/Video/VideoFromImages.mp4\n", | |
"\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
" " | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Moviepy - Done !\n", | |
"Moviepy - video ready /home/j.vangoey/Downloads/RenamedFiles/Video/VideoFromImages.mp4\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"\r" | |
] | |
} | |
], | |
"source": [ | |
"name = 'VideoFromImages'\n", | |
"path = target_dir.resolve() / 'Video'\n", | |
"\n", | |
"batch_up_one_folder.img_to_vid(name, path, fps = 24)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "f7a4edf6", | |
"metadata": { | |
"notebookRunGroups": { | |
"groupValue": "" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# clips = [ed.VideoFileClip(f'{Path.cwd().resolve()}\\\\all\\\\video {(\"0\" + str(i))[-2:]}.mp4') for i in range(1,12)]\n", | |
"\n", | |
"# # concatenating all the clips\n", | |
"# final = ed.concatenate_videoclips(clips)\n", | |
"# #writing the video into a file / saving the combined video\n", | |
"# final.write_videofile(str(Path(\"all/merged.mp4\").resolve()))" | |
] | |
} | |
], | |
"metadata": { | |
"hide_input": false, | |
"kernelspec": { | |
"display_name": "Python 3.7.8 64-bit", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.7.8" | |
}, | |
"vscode": { | |
"interpreter": { | |
"hash": "3fb72c9af01491fffafc3930914c012f9e7e71d6ec4ec8e924ffd924025bf70b" | |
} | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment