Skip to content

Instantly share code, notes, and snippets.

@BioGeek
Created September 12, 2022 08:50
Show Gist options
  • Save BioGeek/4f79528e0ee69ef6cac8f2aa7c05bb56 to your computer and use it in GitHub Desktop.
Save BioGeek/4f79528e0ee69ef6cac8f2aa7c05bb56 to your computer and use it in GitHub Desktop.
Code review of FileOps code
Display the source blob
Display the rendered blob
Raw
{
"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