├── HandBrakeCLI_Colab.ipynb
└── README.md
/HandBrakeCLI_Colab.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "HandyCLI.ipynb",
7 | "private_outputs": true,
8 | "provenance": [],
9 | "collapsed_sections": [
10 | "pCPualPTTLMa",
11 | "a4TZEfjtSF5C",
12 | "a9Zjw2QUTP1A",
13 | "pOJeymyOQzvr"
14 | ]
15 | },
16 | "kernelspec": {
17 | "name": "python3",
18 | "display_name": "Python 3"
19 | }
20 | },
21 | "cells": [
22 | {
23 | "cell_type": "markdown",
24 | "metadata": {
25 | "id": "Bo8JdYqmmUA0"
26 | },
27 | "source": [
28 | "#
\n",
29 | " \n",
30 | "HandBrakeCLI-ColabNotebook v1.3 \n",
31 | "\n",
32 | "Convert/Compress videos using HandBrake in colab.\n",
33 | "\n",
34 | "Give a like and follow 😊"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "0EbCdnXG3b_P"
41 | },
42 | "source": [
43 | "# GOOGLE DRIVE"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "metadata": {
49 | "id": "eYSZh4dJ2D8q",
50 | "cellView": "form"
51 | },
52 | "source": [
53 | "#@title Mount Google Drive \n",
54 | "#@markdown \n",
55 | "#@markdown Use this if and only if you don't use rclone yet. \n",
56 | "#@markdown This may lead to corrupt output file sometimes.\n",
57 | "from google.colab import drive\n",
58 | "drive.mount('/content/drive')"
59 | ],
60 | "execution_count": null,
61 | "outputs": []
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {
66 | "id": "pCPualPTTLMa"
67 | },
68 | "source": [
69 | "#Run These first"
70 | ]
71 | },
72 | {
73 | "cell_type": "code",
74 | "metadata": {
75 | "id": "BuvdTmE_Ersm",
76 | "cellView": "form"
77 | },
78 | "source": [
79 | "#@title <<----Install HandBrake and rClone \n",
80 | "%%capture\n",
81 | "AUTO_RECONNECT = True #@param {type:\"boolean\"}\n",
82 | "HANDBRAKE = True #@param {type:\"boolean\"}\n",
83 | "RCLONE = True #@param {type:\"boolean\"}\n",
84 | "#@markdown Check AUTO_RECONNECT to prevent notebook from disconnecting!\n",
85 | "\n",
86 | "from os import makedirs\n",
87 | "makedirs(\"/content/temp/HandbrakeTemp\", exist_ok = True)\n",
88 | "makedirs(\"/root/.config/rclone\", exist_ok = True) \n",
89 | "if HANDBRAKE==True:\n",
90 | " !wget -qq https://github.com/vot/ffbinaries-prebuilt/releases/download/v4.2.1/ffmpeg-4.2.1-linux-64.zip \n",
91 | " !rm -f ffmpeg-4.2.1-linux-64.zip\n",
92 | " !add-apt-repository ppa:stebbins/handbrake-releases -y \n",
93 | " !apt-get install -y handbrake-cli \n",
94 | " \n",
95 | "if RCLONE==True:\n",
96 | " !curl https://rclone.org/install.sh | sudo bash\n",
97 | "\n",
98 | "if AUTO_RECONNECT:\n",
99 | " import IPython\n",
100 | " from google.colab import output\n",
101 | "\n",
102 | " display(IPython.display.Javascript('''\n",
103 | " function ClickConnect(){\n",
104 | " btn = document.querySelector(\"colab-connect-button\")\n",
105 | " if (btn != null){\n",
106 | " console.log(\"Click colab-connect-button\"); \n",
107 | " btn.click() \n",
108 | " }\n",
109 | " \n",
110 | " btn = document.getElementById('ok')\n",
111 | " if (btn != null){\n",
112 | " console.log(\"Click reconnect\"); \n",
113 | " btn.click() \n",
114 | " }\n",
115 | " }\n",
116 | " \n",
117 | " setInterval(ClickConnect,60000)\n",
118 | " '''))"
119 | ],
120 | "execution_count": null,
121 | "outputs": []
122 | },
123 | {
124 | "cell_type": "code",
125 | "metadata": {
126 | "id": "J-S7hYTzLpZK",
127 | "cellView": "form"
128 | },
129 | "source": [
130 | "#@title <-----Upload your Rclone.config file\n",
131 | "def moveConfig():\n",
132 | " !mv rclone.conf /root/.config/rclone/rclone.conf\n",
133 | "\n",
134 | "from google.colab import files\n",
135 | "\n",
136 | "uploaded = files.upload()\n",
137 | "\n",
138 | "for fn in uploaded.keys():\n",
139 | " print('User uploaded file \"{name}\" with length {length} bytes'.format(\n",
140 | " name=fn, length=len(uploaded[fn])))\n",
141 | "moveConfig()\n",
142 | "print(\"Moved rclone.conf to /root/.config/rclone/rclone.conf\")"
143 | ],
144 | "execution_count": null,
145 | "outputs": []
146 | },
147 | {
148 | "cell_type": "markdown",
149 | "metadata": {
150 | "id": "a4TZEfjtSF5C"
151 | },
152 | "source": [
153 | "# Rclone Mount/Unmount/Copy \n",
154 | " "
155 | ]
156 | },
157 | {
158 | "cell_type": "code",
159 | "metadata": {
160 | "id": "st8Q_ZN27ovN",
161 | "cellView": "form"
162 | },
163 | "source": [
164 | "#@markdown Rclone MOUNT / UNMOUNT Mount the remote as file system on a mountpoint. \n",
165 | "import os\n",
166 | "from IPython.display import HTML, clear_output\n",
167 | "import uuid\n",
168 | "import ipywidgets as widgets\n",
169 | "from google.colab import output\n",
170 | "import re\n",
171 | "##########################################\n",
172 | "\n",
173 | "class MakeButton(object):\n",
174 | " def __init__(self, title, callback, style):\n",
175 | " self._title = title\n",
176 | " self._callback = callback\n",
177 | " self._style = style\n",
178 | " def _repr_html_(self):\n",
179 | " callback_id = 'button-' + str(uuid.uuid4())\n",
180 | " output.register_callback(callback_id, self._callback)\n",
181 | " if self._style != \"\":\n",
182 | " style_html = \"p-Widget jupyter-widgets jupyter-button widget-button mod-\" + self._style\n",
183 | " else:\n",
184 | " style_html = \"p-Widget jupyter-widgets jupyter-button widget-button\"\n",
185 | " template = \"\"\"{title} \n",
186 | " \"\"\"\n",
192 | " html = template.format(title=self._title, callback_id=callback_id, style_html=style_html)\n",
193 | " return html\n",
194 | " \n",
195 | "def ShowAC():\n",
196 | " clear_output(wait=True)\n",
197 | " display(\n",
198 | " widgets.HBox(\n",
199 | " [widgets.VBox(\n",
200 | " [widgets.HTML(\n",
201 | " '''\n",
202 | " Rclone available config... \n",
203 | " '''\n",
204 | " ),\n",
205 | " mountNam]\n",
206 | " )\n",
207 | " ]\n",
208 | " )\n",
209 | " )\n",
210 | " \n",
211 | " display(HTML(\" \"), MakeButton(\"Mount\", MountCMD, \"primary\"),\n",
212 | " MakeButton(\"Unmount\", unmountCMD, \"danger\"))\n",
213 | "content = open(\"/root/.config/rclone/rclone.conf\").read()\n",
214 | "avCon = re.findall(r\"^\\[(.+)\\]$\", content, re.M)\n",
215 | "mountNam = widgets.Dropdown(options=avCon)\n",
216 | "cache_path=\"/content/temp/rCloneTemp\"\n",
217 | "def MountCMD():\n",
218 | " mPoint = f\"/content/drives/{mountNam.value}\"\n",
219 | " os.makedirs(mPoint, exist_ok=True)\n",
220 | " !rclone mount $mountNam.value: $mPoint --user-agent 'Mozilla' --buffer-size 256M --transfers 10 --vfs-cache-mode minimal --vfs-read-chunk-size 500M --vfs-cache-max-size 50G --vfs-cache-max-age 0h0m1s --vfs-cache-poll-interval 0m1s --cache-dir '/content/temp/rCloneTemp' --allow-other --daemon \n",
221 | "\n",
222 | " if os.path.isdir(mPoint)== True:\n",
223 | " print(f\"Mount success! - \\t{mPoint}\")\n",
224 | " else:\n",
225 | " print(f\"Mount failed! - \\t{mPoint}\")\n",
226 | "\n",
227 | "def unmountCMD():\n",
228 | " mPoint = f\"/content/drives/{mountNam.value}\"\n",
229 | " if os.system(f\"fusermount -uz {mPoint}\") == 0:\n",
230 | " runSh(f\"rm -r {mPoint}\")\n",
231 | " print(f\"Unmounted success! - \\t{mPoint}\")\n",
232 | " else:\n",
233 | " runSh(f\"fusermount -uz {mPoint}\", output=True)\n",
234 | "\n",
235 | "ShowAC()"
236 | ],
237 | "execution_count": null,
238 | "outputs": []
239 | },
240 | {
241 | "cell_type": "code",
242 | "metadata": {
243 | "id": "EiHlpwVDOjhx",
244 | "cellView": "form"
245 | },
246 | "source": [
247 | " \n",
248 | "#@markdown \n",
249 | " \n",
250 | "#@markdown ---\n",
251 | "source = \"\" #@param {type:\"string\"}\n",
252 | "destination = \"\" #@param {type:\"string\"}\n",
253 | "mode = \"copy\" #@param [\"copy\", \"check\"]\n",
254 | "dry_run = False #@param {type:\"boolean\"}\n",
255 | "Extra_args = \"\" #@param {type:\"string\"}\n",
256 | "#@markdown ---\n",
257 | "Email_notification = False #@param {type:\"boolean\"}\n",
258 | "logs = False #@param {type:\"boolean\"}\n",
259 | "emailID = \"\" #@param {type:\"string\"}\n",
260 | "password = \"\" #@param {type:\"string\"}\n",
261 | "Receiver_ID = \"\" #@param {type:\"string\"}\n",
262 | "#@markdown ---\n",
263 | "import smtplib \n",
264 | "########################################\n",
265 | "args = \"--transfers 20 --checkers 20 --stats-one-line --stats=5s -v --tpslimit 95 --tpslimit-burst 40 \"\n",
266 | "if mode == \"check\":\n",
267 | " args += \"--one-way \"\n",
268 | "if dry_run == True:\n",
269 | " args +=\" --dry-run \"\n",
270 | "if logs == True:\n",
271 | " args += \" --log-file rClone_log.txt \"\n",
272 | "if Extra_args != \"\":\n",
273 | " args +=Extra_args\n",
274 | "######################################\n",
275 | "def runrClone():\n",
276 | " !rclone --user-agent \"Mozilla\" \"$mode\" \"$source\" \"$destination\" $args\n",
277 | " \n",
278 | "def checkEmail():\n",
279 | " if (Email_notification == True and logs == False):\n",
280 | " print(\"You will receive only a notification after task has finished.\")\n",
281 | " runrClone()\n",
282 | " #Send only notification\n",
283 | " \n",
284 | " s = smtplib.SMTP('smtp.gmail.com', 587) \n",
285 | " s.starttls() \n",
286 | " s.login(emailID , password)\n",
287 | " message = \"Your rClone task has Completed!\"\n",
288 | " s.sendmail(emailID, Receiver_ID, message)\n",
289 | " print(\"Email Alert Sent!\") \n",
290 | " s.quit()\n",
291 | " elif (Email_notification == True and logs == True):\n",
292 | " print(\"You will receive a notification with log attached after task has finished.\")\n",
293 | " runrClone()\n",
294 | " #Sending email notification with logs\n",
295 | " \n",
296 | " from email.mime.multipart import MIMEMultipart \n",
297 | " from email.mime.text import MIMEText \n",
298 | " from email.mime.base import MIMEBase \n",
299 | " from email import encoders \n",
300 | "\n",
301 | " fromaddr = emailID\n",
302 | " toaddr = Receiver_ID\n",
303 | " msg = MIMEMultipart() \n",
304 | " # storing the senders email address \n",
305 | " msg['From'] = fromaddr \n",
306 | " # storing the receivers email address \n",
307 | " msg['To'] = toaddr \n",
308 | " # storing the subject \n",
309 | " msg['Subject'] = \"Colab has Finished Running your Cell\"\n",
310 | " # string to store the body of the mail \n",
311 | " body = \"Your rClone Task has Completed! Visit link to view : https://colab.research.google.com/github/SKGHD/Handy/blob/master/HandBrakeCLI_Colab.ipynb\"\n",
312 | "\n",
313 | " msg.attach(MIMEText(body, 'plain'))\n",
314 | " filename = \"rClone_log.txt\"\n",
315 | " attachment = open(\"/content/rClone_log.txt\", \"rb\")\n",
316 | " p = MIMEBase('application', 'octet-stream') \n",
317 | " p.set_payload((attachment).read()) \n",
318 | " # encode into base64 \n",
319 | " encoders.encode_base64(p) \n",
320 | " \n",
321 | " p.add_header('Content-Disposition', \"attachment; filename= %s\" % filename) \n",
322 | " msg.attach(p) \n",
323 | " s = smtplib.SMTP('smtp.gmail.com', 587) \n",
324 | " s.starttls() \n",
325 | " s.login(fromaddr, password) \n",
326 | " text = msg.as_string() \n",
327 | " s.sendmail(fromaddr, toaddr, text)\n",
328 | " print(\"Email Alert Sent with log!\") \n",
329 | " s.quit() \n",
330 | " elif (Email_notification == False and logs == False):\n",
331 | " print(\"You will not receive any notification!!!.\")\n",
332 | " runrClone()\n",
333 | "checkEmail()"
334 | ],
335 | "execution_count": null,
336 | "outputs": []
337 | },
338 | {
339 | "cell_type": "markdown",
340 | "metadata": {
341 | "id": "a9Zjw2QUTP1A"
342 | },
343 | "source": [
344 | "# ***HandBrake*** \n",
345 | "# "
346 | ]
347 | },
348 | {
349 | "cell_type": "code",
350 | "metadata": {
351 | "id": "Jdu112hxo6_M",
352 | "cellView": "form"
353 | },
354 | "source": [
355 | "#@title HandBrake Configuration \n",
356 | "#@markdown > Select Mode ( Batch conversion/ Single File)\n",
357 | "MODE = \"SINGLE\" #@param [\"SINGLE\", \"BATCH\"]\n",
358 | "\n",
359 | "\n",
360 | "#@markdown ---\n",
361 | "SOURCE = \"\" #@param {type:\"string\"}\n",
362 | "DESTINATION = \"\" #@param {type:\"string\"}\n",
363 | "FORMAT = \"mp4\" #@param [\"mp4\", \"mkv\"]\n",
364 | "RESOLUTION = \"480p\" #@param [\"360p\", \"480p\",\"540p\", \"720p\", \"1080p\"]\n",
365 | "Encoder = \"x264\" #@param [\"x264\", \"x265\"]\n",
366 | "Encoder_Preset = \"ultrafast\" #@param [\"ultrafast\", \"faster\", \"fast\", \"medium\", \"slow\", \"slower\"]\n",
367 | "#@markdown Choose Constant Quality Rate [Lower = Higher Quality/\n",
368 | "#@markdown Larger File Size]\n",
369 | "CQ = 30 #@param {type:\"slider\", min:10, max:30, step:1}\n",
370 | "BURN_SUBTITLES = False #@param {type:\"boolean\"}\n",
371 | "Additional_Flags = \"\" #@param {type:\"string\"}\n",
372 | "#@markdown ---\n",
373 | "Email_Alert = False #@param {type:\"boolean\"}\n",
374 | "MESSAGE = \"HandBrakeCLI_Colab has finished working\" #@param [\"HandBrake has finished working\"] {allow-input: true}\n",
375 | "SENDER_ID =\"\" #@param {type:\"string\"}\n",
376 | "SENDER_PASS=\"\" #@param {type:\"string\"}\n",
377 | "RECEIVER_ID=\"\" #@param {type:\"string\"}\n",
378 | "#@markdown >##### Using an app specific password is recommended: https://myaccount.google.com/apppasswords\n",
379 | "\n",
380 | "########################################################\n",
381 | "import smtplib\n",
382 | "import os\n",
383 | "\n",
384 | "\n",
385 | "formats = ('.mkv','.mp4','.ts','.avi','.mov','.wmv')\n",
386 | "\n",
387 | "######## Renames the file ########\n",
388 | "def fileName(fPath):\n",
389 | " tName = fPath.split('/')[-1] \n",
390 | " if tName.endswith('ts'):\n",
391 | " tName = '[HANDY] ' + tName[:-3] + f' [{RESOLUTION}] [{Encoder}].{FORMAT}' \n",
392 | " else:\n",
393 | " tName = '[HANDY] ' + tName[:-4] + f' [{RESOLUTION}] [{Encoder}].{FORMAT}' \n",
394 | " return tName\n",
395 | "\n",
396 | "def set_resolution():\n",
397 | " global w,h,flags\n",
398 | " if RESOLUTION == \"360p\":\n",
399 | " w, h = \"480\" , \"360\"\n",
400 | " elif RESOLUTION == \"480p\":\n",
401 | " w, h = \"854\" , \"480\"\n",
402 | " elif RESOLUTION == \"540p\":\n",
403 | " w, h = \"960\" , \"540\"\n",
404 | " elif RESOLUTION == \"720p\":\n",
405 | " w, h = \"1280\" , \"720\"\n",
406 | " elif RESOLUTION == \"1080p\":\n",
407 | " w, h = \"1920\" , \"1080\"\n",
408 | "\n",
409 | "def addFlags():\n",
410 | " global flags\n",
411 | " flags = f\" --encoder {Encoder} --all-audio -s '0,1,2,3' --cfr --optimize --quality={CQ} --width={w} --height={h} --format={FORMAT} --encoder-preset={Encoder_Preset} \"\n",
412 | " if BURN_SUBTITLES:\n",
413 | " flags += \"-s '1' --subtitle-burned '1' \"\n",
414 | " if Additional_Flags != \"\":\n",
415 | " flags += str(Additional_Flags)\n",
416 | "\n",
417 | "set_resolution()\n",
418 | "addFlags()\n",
419 | "\n",
420 | "##### HandBrake and Rclone #####\n",
421 | "def runner(path):\n",
422 | " f_name = fileName(path)\n",
423 | " hTemp=f\"/content/temp/HandbrakeTemp/{f_name}\"\n",
424 | " !HandBrakeCLI -i \"$path\" -o \"$hTemp\" $flags\n",
425 | " \n",
426 | " \n",
427 | " if os.path.isfile(hTemp):\n",
428 | " print(f\"\\n\\n********** Successfully converted {f_name}\\n Now saving to Destination.....\")\n",
429 | " if os.path.exists('/usr/bin/rclone'):\n",
430 | " !rclone move \"$hTemp\" --user-agent \"Mozilla\" \"$DESTINATION\" --transfers 20 --checkers 20 --stats-one-line --stats=5s -v --tpslimit 95 --tpslimit-burst 40\n",
431 | " else:\n",
432 | " dest = DESTINATION+'/'+f_name\n",
433 | " !mv \"$hTemp\" \"$dest\"\n",
434 | " if os.path.isfile(DESTINATION+ '/' +f_name): \n",
435 | " print(f\"\\n\\n********** Successfully saved {f_name} to Destination\")\n",
436 | "\n",
437 | "########## Check Mode ########\n",
438 | "if MODE==\"BATCH\":\n",
439 | " os.makedirs(DESTINATION, exist_ok=True)\n",
440 | " if SOURCE.endswith('/'):\n",
441 | " pass\n",
442 | " else: SOURCE +='/'\n",
443 | " filesList = os.listdir(SOURCE+'.')\n",
444 | " if os.path.isfile(SOURCE+'processed_db.txt'):\n",
445 | " pass\n",
446 | " else:\n",
447 | " with open((SOURCE+'processed_db.txt'), 'w') as fb:\n",
448 | " fb.write(\"Do not delete this file until all files have been processed!\\n\")\n",
449 | " fb.close()\n",
450 | " with open((SOURCE+'processed_db.txt'), \"r+\") as filehandle:\n",
451 | " processedList = [x.rstrip() for x in filehandle.readlines()]\n",
452 | "\n",
453 | " print('<<<<<<<<<<<<<<<<<< Starting Conversion in Batch mode. >>>>>>>>>>>>>>>>>>')\n",
454 | "\n",
455 | " for currentFile in filesList:\n",
456 | " if currentFile.endswith(formats):\n",
457 | " if currentFile not in processedList:\n",
458 | " currentPath = SOURCE + currentFile \n",
459 | " print(f'\\n\\n**************** Current File to process: {currentFile}')\n",
460 | " runner(currentPath)\n",
461 | " filehandle.write(currentFile+'\\n')\n",
462 | " filehandle.close()\n",
463 | " \n",
464 | "\n",
465 | "else:\n",
466 | " if SOURCE.endswith(formats): \n",
467 | " runner(SOURCE)\n",
468 | " else: print(\"Are you sure you have selected the correct file??\")\n",
469 | "\n",
470 | "########### Sending Notification ###############\n",
471 | "if Email_Alert == True: \n",
472 | " from email.mime.multipart import MIMEMultipart \n",
473 | " from email.mime.text import MIMEText \n",
474 | " msg = MIMEMultipart()\n",
475 | " msg['From'] = SENDER_ID\n",
476 | " msg['To'] = RECEIVER_ID\n",
477 | " msg['Subject'] = \"HandBrakeCLI_Colab has finished executing!\" \n",
478 | " \n",
479 | " msg.attach(MIMEText(MESSAGE))\n",
480 | " s = smtplib.SMTP('smtp.gmail.com', 587) \n",
481 | " s.starttls() \n",
482 | " s.login(SENDER_ID, SENDER_PASS)\n",
483 | " s.sendmail(SENDER_ID, RECEIVER_ID, msg.as_string())\n",
484 | " print(\"Email Alert Sent!\") \n",
485 | " s.quit()\n"
486 | ],
487 | "execution_count": null,
488 | "outputs": []
489 | },
490 | {
491 | "cell_type": "markdown",
492 | "metadata": {
493 | "id": "YceU6ECgzFxG"
494 | },
495 | "source": [
496 | "# Audio Video Tools"
497 | ]
498 | },
499 | {
500 | "cell_type": "code",
501 | "metadata": {
502 | "id": "CCn6s3RvzO9o"
503 | },
504 | "source": [
505 | "#@title Extract 🎼Audio from Video 🎞 { display-mode: \"form\" }\n",
506 | "import os\n",
507 | "Input_File = \"Paste/Path/to/video_file.mp4\" #@param {type:\"string\"}\n",
508 | "Output_File_Name = \"extracted_audio.mp3\" #@param {type:\"string\"}\n",
509 | "fPath = os.path.dirname(Input_File) +'/'+ Output_File_Name\n",
510 | "\n",
511 | "\n",
512 | "!ffmpeg -i Input_File -vn -acodec copy fPath\n",
513 | "#@markdown >##### Save file name with extension like .mp3, .aac "
514 | ],
515 | "execution_count": null,
516 | "outputs": []
517 | },
518 | {
519 | "cell_type": "code",
520 | "metadata": {
521 | "id": "SuIsOEllzgOH"
522 | },
523 | "source": [
524 | "#@title Remove Audio 🎼 from Video 🎞 { display-mode: \"form\" }\n",
525 | "\n",
526 | "import os\n",
527 | "Input_File = \"Paste/Path/to/video_file.mp4\" #@param {type:\"string\"}\n",
528 | "Output_File_Name = \"video_file_without_audio.mp4\" #@param {type:\"string\"}\n",
529 | "fPath = os.path.dirname(Input_File) +'/'+ Output_File_Name\n",
530 | "\n",
531 | "!ffmpeg -i Input_File -codec copy -an fPath\n",
532 | "\n"
533 | ],
534 | "execution_count": null,
535 | "outputs": []
536 | },
537 | {
538 | "cell_type": "code",
539 | "metadata": {
540 | "cellView": "form",
541 | "id": "9NxOZ-kr-xBp"
542 | },
543 | "source": [
544 | "#@title Extract Images 🖼 from a Video 🎞🎞\n",
545 | "import os\n",
546 | "Input_File = \"Paste/Path/to/video_file.mp4\" #@param {type:\"string\"}\n",
547 | "dir_path = os.path.dirname(Input_File)\n",
548 | "os.makedirs(os.path.join(dir_path,'Extracted_Images'))\n",
549 | "!ffmpeg -i Input_File dir_path/Extracted_Images/image%d.jpg"
550 | ],
551 | "execution_count": null,
552 | "outputs": []
553 | },
554 | {
555 | "cell_type": "markdown",
556 | "metadata": {
557 | "id": "SyR9RfbxIloN"
558 | },
559 | "source": [
560 | "# Testing Area(Unfinished)"
561 | ]
562 | },
563 | {
564 | "cell_type": "code",
565 | "metadata": {
566 | "cellView": "form",
567 | "id": "w2rRu1U0rXdF"
568 | },
569 | "source": [
570 | " \n",
571 | "#@markdown \n",
572 | "#@markdown Unlimited Transfer \n",
573 | "#@markdown >##### You'll need to manually enter remote names but this doesn't rely on colab's storage so you can transfer as much as you need without limits.\n",
574 | "#@markdown ---\n",
575 | "source = \"\" #@param {type:\"string\"}\n",
576 | "source_remote = \"\" #@param {type:\"string\"}\n",
577 | "destination = \"\" #@param {type:\"string\"}\n",
578 | "destination_remote = \"\" #@param {type:\"string\"}\n",
579 | "mode = \"copy\" #@param [\"copy\", \"check\", \"sync\"]\n",
580 | "dry_run = False #@param {type:\"boolean\"}\n",
581 | "Extra_args = \"\" #@param {type:\"string\"}\n",
582 | "#@markdown ---\n",
583 | "Email_notification = True #@param {type:\"boolean\"}\n",
584 | "logs = False #@param {type:\"boolean\"}\n",
585 | "emailID = \"\" #@param {type:\"string\"}\n",
586 | "password = \"\" #@param {type:\"string\"}\n",
587 | "Receiver_ID = \"\" #@param {type:\"string\"}\n",
588 | "#@markdown ---\n",
589 | "import smtplib \n",
590 | "########################################\n",
591 | "#args = \"--transfers 20 --checkers 20 --stats-one-line --stats=5s -v --tpslimit 95 --tpslimit-burst 40 \"\n",
592 | "args = \" --stats-one-line --stats=5s -v \"\n",
593 | "if mode == \"check\":\n",
594 | " args += \"--one-way \"\n",
595 | "if dry_run == True:\n",
596 | " args +=\" --dry-run \"\n",
597 | "if logs == True:\n",
598 | " args += \" --log-file rClone_log.txt \"\n",
599 | "if Extra_args != \"\":\n",
600 | " args +=Extra_args\n",
601 | "######################################\n",
602 | "def runrClone():\n",
603 | " !rclone --user-agent \"Mozilla\" \"$mode\" $source_remote:\"$source\" $destination_remote:\"$destination\" $args\n",
604 | " \n",
605 | "def checkEmail():\n",
606 | " if (Email_notification == True and logs == False):\n",
607 | " print(\"You will receive only a notification after task has finished.\")\n",
608 | " runrClone()\n",
609 | " #Send only notification\n",
610 | " \n",
611 | " s = smtplib.SMTP('smtp.gmail.com', 587) \n",
612 | " s.starttls() \n",
613 | " s.login(emailID , password)\n",
614 | " message = \"Your rClone task has Completed!\"\n",
615 | " s.sendmail(emailID, Receiver_ID, message)\n",
616 | " print(\"Email Alert Sent!\") \n",
617 | " s.quit()\n",
618 | " elif (Email_notification == True and logs == True):\n",
619 | " print(\"You will receive a notification with log attached after task has finished.\")\n",
620 | " runrClone()\n",
621 | " #Sending email notification with logs\n",
622 | " \n",
623 | " from email.mime.multipart import MIMEMultipart \n",
624 | " from email.mime.text import MIMEText \n",
625 | " from email.mime.base import MIMEBase \n",
626 | " from email import encoders \n",
627 | "\n",
628 | " fromaddr = emailID\n",
629 | " toaddr = Receiver_ID\n",
630 | " msg = MIMEMultipart() \n",
631 | " # storing the senders email address \n",
632 | " msg['From'] = fromaddr \n",
633 | " # storing the receivers email address \n",
634 | " msg['To'] = toaddr \n",
635 | " # storing the subject \n",
636 | " msg['Subject'] = \"Colab has Finished Running your Cell\"\n",
637 | " # string to store the body of the mail \n",
638 | " body = \"Your rClone Task has Completed! Visit link to view : https://colab.research.google.com/github/SKGHD/Handy/blob/master/HandyCLI.ipynb\"\n",
639 | "\n",
640 | " msg.attach(MIMEText(body, 'plain'))\n",
641 | " filename = \"rClone_log.txt\"\n",
642 | " attachment = open(\"/content/rClone_log.txt\", \"rb\")\n",
643 | " p = MIMEBase('application', 'octet-stream') \n",
644 | " p.set_payload((attachment).read()) \n",
645 | " # encode into base64 \n",
646 | " encoders.encode_base64(p) \n",
647 | " \n",
648 | " p.add_header('Content-Disposition', \"attachment; filename= %s\" % filename) \n",
649 | " msg.attach(p) \n",
650 | " s = smtplib.SMTP('smtp.gmail.com', 587) \n",
651 | " s.starttls() \n",
652 | " s.login(fromaddr, password) \n",
653 | " text = msg.as_string() \n",
654 | " s.sendmail(fromaddr, toaddr, text)\n",
655 | " print(\"Email Alert Sent with log!\") \n",
656 | " s.quit() \n",
657 | " elif (Email_notification == False and logs == False):\n",
658 | " print(\"You will not receive any notification!!!.\")\n",
659 | " runrClone()\n",
660 | "checkEmail()"
661 | ],
662 | "execution_count": null,
663 | "outputs": []
664 | }
665 | ]
666 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HandBrakeCLI-ColabNotebook v1.3
2 |
3 | Consider giving this repo a star ⭐ if it helped you.
4 |
5 |
6 |
7 | Features:
8 | Mount/Unmount your Cloud drive with rClone.
9 | Transfer files between your cloud drives with the speed of google's fast servers.
10 | Convert videos online with the help of HandBrake.
11 | Batch Convert directories.
12 | Resume support for Batch conversion jobs. Pick up right after the last successful conversion in Batch Job when your colab notebook restarts or disconnects.
13 | Get email notification when your task(s) have finished.
14 | Extract audio from video clips!
15 | Remove audio from video clips!
16 | Extract images from video clips!
17 |
18 |
19 | # Usage
20 |
21 | Click on the "Open in Colab" button.
22 | [](https://colab.research.google.com/github/SKGHD/Handy/blob/master/HandBrakeCLI_Colab.ipynb)
23 |
24 | # Notes
25 |
26 | To use email notifications only gmail id can be used and use an app specfic password Google account settings in order for the feature to work.
27 | Only you and those who can see your screen physically can see your passwords.
28 | Your passwords are stored in a local variable in your Jupyter Notebook and not stored anywhere less. It gets automatically destroyed when Google purges your notebook.
29 | Do not remove processed_db.txt from your current batch directory else it'll process same files again and again each time you restart the notebook!
30 |
31 | Read more about app specific passwords here: Google Account Help
32 |
33 | # FAQs
34 |
35 |
Q> What is rclone? How do I get rclone.conf file?
36 | A> Everything has been answer here in this forum. Please have a read :Rclone
37 | Q> How to add more flags to the script?
38 | A> Just add them to the Additional_Flags: ______ in below format.
39 | Example:
40 | `--bframes '8' rc-lookahead '40' no-rect`
41 |
42 | Note: Numbers should be in single quotes.
43 |
44 | Q> Where do I ask for help or feature requests?
45 | A> Open a new request or issue here in github. Please don't message me directly.
46 |
47 | ### Handbrake CLI reference
48 |
49 | Read more about CLI commands here: Handbrake CLI Docs
50 |
51 |
52 | ## Pull Requests are welcome.
53 |
--------------------------------------------------------------------------------