{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "source": [ "# YouTube to WebDAV\n", "This script allows for a YouTube video to be downloaded and then automatically uplaoded via WebDAV\n", "\n", "Usecase is useful for running Syncplay or similar software in situations where running yt-dlp may not be viable\n", "\n", "This approach can still fail in cases where JS solver is required\n", "\n", "# What this does?\n", "- Downloads vidoe via yt-dlp\n", "- Downloads all official subtitles (non-auto-generated)\n", "- Mux into single MKV file\n", "- Upload via WebDav\n", "\n", "Optionally if you are using Nextcloud you can also automatically generate a share\n", "\n", "# Usage\n", "Fill in all the fields below. Then `Run all`" ], "metadata": { "id": "L9cXBP9OPmFt" } }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "vHGZttQWK8QJ" }, "outputs": [], "source": [ "# Install the dependencies needed\n", "!pip install yt-dlp webdavclient3" ] }, { "cell_type": "code", "source": [ "from webdav3.client import Client\n", "webdav_url = \"\" #@param {type:\"string\"}\n", "username = \"\" #@param {type:\"string\"}\n", "password = \"\" #@param {type:\"string\"}\n", "options = {\n", " 'webdav_hostname': webdav_url,\n", " 'webdav_login': username,\n", " 'webdav_password': password\n", "}\n", "client = Client(options)\n", "try:\n", " client.list()\n", " print(\"Success! Connection successful\")\n", "except:\n", " print(\"Login failed. Please check that your login and WebDAV url are correct\")" ], "metadata": { "cellView": "form", "id": "GAdz5SlkOIJO" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "youtube_url = \"\" #@param{type:\"string\"}\n", "\n", "!yt-dlp -f 'bv*+ba/best' \\\n", " --merge-output-format mkv \\\n", " --embed-subs \\\n", " --write-subs \\\n", " --sub-langs all \\\n", " \"$youtube_url\"" ], "metadata": { "cellView": "form", "id": "GtiPVBYSQ1_6" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# Uploads the file to the path specified\n", "download_path = \"\" #@param{type:\"string\"}\n", "\n", "import glob\n", "\n", "mkv_files = glob.glob(\"/content/*.mkv\")\n", "sub_files = glob.glob(\"/content/*.vtt\") + glob.glob(\"/content/*.srt\")\n", "if not mkv_files:\n", " raise FileNotFoundError(\"MKV file not found! Did the download fail?\")\n", "original_mkv_path = mkv_files[0]\n", "remote_filename = f\"{download_path}/\" + original_mkv_path.split(\"/\")[-1]\n", "client.upload_sync(remote_path=remote_filename, local_path=original_mkv_path)\n", "\n", "print(f\"Done! Your file has been uploaded to {remote_filename}\")" ], "metadata": { "cellView": "form", "id": "3xYJpTl5SeVz" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# OPTIONAL NEXTCLOUD AUTO SHARE\n", "- This uses Nextcloud API to create a public share URL automatically. Completes the workflow" ], "metadata": { "id": "uabtse49Vy-L" } }, { "cell_type": "code", "source": [ "import requests\n", "nextcloud_url = \"\" #@param {type:\"string\"}\n", "api_url = f\"{nextcloud_url}/ocs/v2.php/apps/files_sharing/api/v1/shares\"\n", "payload = {\n", " \"path\": remote_filename,\n", " \"shareType\": 3, # 3 = public link\n", " \"permissions\": 31 # optional, full permissions (read/write/share)\n", "}\n", "\n", "headers = {\n", " \"OCS-APIRequest\": \"true\"\n", "}\n", "response = requests.post(api_url, auth=(username, password), headers=headers, data=payload)\n", "if response.status_code == 200:\n", " import xml.etree.ElementTree as ET\n", " root = ET.fromstring(response.content)\n", " ns = {\"ocs\": \"http://open-collaboration-services.org/ns\"}\n", " url_elem = root.find(\".//url\")\n", " if url_elem is not None:\n", " share_link = url_elem.text\n", " print(\"Share link:\", share_link+\"/download\")\n", " else:\n", " print(\"Could not find share URL in response\")\n", "else:\n", " print(\"Error:\", response.status_code, response.text)" ], "metadata": { "cellView": "form", "id": "MSmhsS6PUxaG" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# Cleanup/Delete old files\n", "import os\n", "mkv_files = glob.glob(\"/content/*.mkv\")\n", "sub_files = glob.glob(\"/content/*.vtt\") + glob.glob(\"/content/*.srt\")\n", "for f in mkv_files + sub_files:\n", " os.remove(f)\n", " print(f\"Deleted local file: {f}\")" ], "metadata": { "id": "xBprVc4OUCor" }, "execution_count": null, "outputs": [] } ] }