{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 🚀 AI Video 4K Upscaler (Google Colab Tesla T4 - PyTorch CUDA Engine)\n",
    "Pipeline tự động nâng cấp 8 tập phim lịch sử từ 720p lên 4K UHD bằng **Real-ESRGAN x4plus (PyTorch CUDA Native)** trên GPU Tesla T4 16GB.\n",
    "- ✅ **100% Native CUDA**: Sử dụng nhân Tensor Cores FP16 trực tiếp từ PyTorch (không bị lỗi driver Vulkan).\n",
    "- ✅ **Đã fix triệt để lỗi setuptools & basicsr**: Khắc phục lỗi `KeyError: '__version__'` trên môi trường Colab mới.\n",
    "- ✅ **Hiển thị tiến độ real-time**: Thanh tiến độ `tqdm` hiển thị từng frame, tốc độ fps và thời gian còn lại.\n",
    "- ✅ **Lưu trực tiếp về Google Drive**: Thành phẩm 4K tự động lưu vào thư mục `Historical_Videos_4K` trên Drive của bạn."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# [BƯỚC 1] Kiểm tra GPU Tesla T4 (16GB VRAM)\n",
    "!nvidia-smi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# [BƯỚC 2] Cài đặt Real-ESRGAN Native PyTorch CUDA (Đã fix triệt để lỗi setuptools / KeyError)\n",
    "import os\n",
    "\n",
    "# 1. Khóa setuptools < 70 để triệt tiêu lỗi KeyError: '__version__' của basicsr\n",
    "!pip install -q \"setuptools<70\" wheel\n",
    "\n",
    "# 2. Cài đặt basicsr với cờ --no-build-isolation\n",
    "!pip install -q basicsr --no-build-isolation\n",
    "!pip install -q facexlib gfpgan ffmpeg-python gdown\n",
    "!apt-get -qq update && apt-get -qq install -y ffmpeg\n",
    "\n",
    "# 3. Vá lỗi tương thích torchvision trong basicsr\n",
    "!find /usr/local/lib/python3* -name \"degradations.py\" -exec sed -i 's/from torchvision.transforms.functional_tensor import rgb_to_grayscale/from torchvision.transforms.functional import rgb_to_grayscale/g' {} + 2>/dev/null || true\n",
    "\n",
    "# 4. Clone và vá lỗi setup.py của Real-ESRGAN\n",
    "!if [ ! -d \"/content/Real-ESRGAN\" ]; then git clone https://github.com/xinntao/Real-ESRGAN.git /content/Real-ESRGAN; fi\n",
    "%cd /content/Real-ESRGAN\n",
    "!sed -i \"s/return locals()\\[ '__version__' \\]/return '0.3.0'/g\" setup.py 2>/dev/null || true\n",
    "!sed -i \"s/return locals()\\[ '__version__'\\]/return '0.3.0'/g\" setup.py 2>/dev/null || true\n",
    "!python -c \"content = open('setup.py').read().replace(\\\"return locals()['__version__']\\\", \\\"return '0.3.0'\\\"); open('setup.py', 'w').write(content)\"\n",
    "!python setup.py develop -q\n",
    "\n",
    "# 5. Tải trọng số model AI RealESRGAN_x4plus (chuyên cho nhân vật người thật & cảnh lịch sử)\n",
    "!mkdir -p experiments/pretrained_models\n",
    "!wget -q -N https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P experiments/pretrained_models\n",
    "\n",
    "# 6. Kiểm tra xác thực import thành công\n",
    "import torch\n",
    "from basicsr.archs.rrdbnet_arch import RRDBNet\n",
    "from realesrgan import RealESRGANer\n",
    "print(f\"\\n✓ GPU KÍCH HOẠT THÀNH CÔNG: {torch.cuda.get_device_name(0)}\")\n",
    "print(\"✓ THƯ VIỆN BASICSR VÀ REAL-ESRGAN ĐÃ SẴN SÀNG!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# [BƯỚC 3] Tự động tải 8 tập phim từ link Google Drive của bạn\n",
    "import os\n",
    "from pathlib import Path\n",
    "\n",
    "FOLDER_URL = \"https://drive.google.com/drive/folders/1h8Nsh4j8vrqf956rnx78ENnWBMJxpDTc\"\n",
    "LOCAL_INPUT_DIR = \"/content/input_videos\"\n",
    "os.makedirs(LOCAL_INPUT_DIR, exist_ok=True)\n",
    "\n",
    "print(\"Đang quét và tải 8 tập phim từ Google Drive về Colab SSD...\")\n",
    "!gdown --folder \"{FOLDER_URL}\" -O \"{LOCAL_INPUT_DIR}\"\n",
    "\n",
    "video_list = sorted([str(p) for p in Path(LOCAL_INPUT_DIR).glob(\"*.mp4\") if not p.name.endswith(\"_4k.mp4\")])\n",
    "print(f\"\\n✓ ĐÃ SẴN SÀNG {len(video_list)} TẬP PHIM ĐỂ NÂNG CẤP 4K:\")\n",
    "for v in video_list:\n",
    "    size_mb = round(os.path.getsize(v) / (1024*1024), 1)\n",
    "    print(f\"  - {os.path.basename(v)} ({size_mb} MB)\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# [BƯỚC 4] Kết nối Google Drive để lưu video 4K thành phẩm\n",
    "from google.colab import drive\n",
    "drive.mount('/content/drive')\n",
    "\n",
    "DRIVE_OUTPUT_DIR = \"/content/drive/MyDrive/Historical_Videos_4K\"\n",
    "os.makedirs(DRIVE_OUTPUT_DIR, exist_ok=True)\n",
    "print(f\"✓ Thư mục lưu video 4K trên Google Drive của bạn:\\n  {DRIVE_OUTPUT_DIR}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# [BƯỚC 5] BẮT ĐẦU CHẠY 4K BATCH UPSCALER (CUDA FP16 TENSOR CORES)\n",
    "import os\n",
    "import time\n",
    "import subprocess\n",
    "from pathlib import Path\n",
    "\n",
    "%cd /content/Real-ESRGAN\n",
    "\n",
    "print(f\"Tìm thấy {len(video_list)} tập cần xử lý...\")\n",
    "\n",
    "for idx, video_path in enumerate(video_list, 1):\n",
    "    in_file = Path(video_path)\n",
    "    expected_out = Path(DRIVE_OUTPUT_DIR) / f\"{in_file.stem}_4k.mp4\"\n",
    "    \n",
    "    # Bỏ qua nếu tập này đã có trên Google Drive (>50MB)\n",
    "    if expected_out.exists() and expected_out.stat().st_size > 50 * 1024 * 1024:\n",
    "        print(f\"\\n[{idx}/{len(video_list)}] ⏭️ Bỏ qua {in_file.name} (Đã có file 4K: {round(expected_out.stat().st_size/(1024*1024), 1)} MB)\")\n",
    "        continue\n",
    "\n",
    "    print(f\"\\n==================================================\")\n",
    "    print(f\"[{idx}/{len(video_list)}] BẮT ĐẦU NÂNG CẤP 4K: {in_file.name}\")\n",
    "    print(f\"GPU: Tesla T4 (PyTorch CUDA Native, FP16, Model RealESRGAN_x4plus)\")\n",
    "    print(f\"==================================================\")\n",
    "    \n",
    "    start_t = time.time()\n",
    "    \n",
    "    # Gọi trực tiếp inference_realesrgan_video.py với CUDA native và tile 512\n",
    "    cmd = [\n",
    "        \"python\", \"inference_realesrgan_video.py\",\n",
    "        \"-i\", str(in_file),\n",
    "        \"-o\", str(DRIVE_OUTPUT_DIR),\n",
    "        \"-n\", \"RealESRGAN_x4plus\",\n",
    "        \"-s\", \"4\",\n",
    "        \"--suffix\", \"4k\",\n",
    "        \"--tile\", \"512\"\n",
    "    ]\n",
    "    \n",
    "    process = subprocess.run(cmd)\n",
    "    \n",
    "    elapsed_m = round((time.time() - start_t) / 60, 2)\n",
    "    if process.returncode == 0 and expected_out.exists():\n",
    "        size_mb = round(expected_out.stat().st_size / (1024*1024), 2)\n",
    "        print(f\"\\n--> ✓ HOÀN TẤT {in_file.name} TRONG {elapsed_m} PHÚT!\")\n",
    "        print(f\"    File 4K: {expected_out.name} ({size_mb} MB) đã lưu an toàn trên Google Drive.\")\n",
    "    else:\n",
    "        print(f\"\\n--> [X] Lỗi xử lý {in_file.name} (Return code: {process.returncode}).\")\n",
    "\n",
    "print(f\"\\n==================================================\")\n",
    "print(\"🎉 CHÚC MỪNG! TOÀN BỘ 8 TẬP PHIM ĐÃ NÂNG CẤP 4K XONG!\")\n",
    "print(f\"Thư mục kết quả trên Drive: {DRIVE_OUTPUT_DIR}\")\n",
    "print(\"==================================================\")"
   ]
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "gpuType": "T4",
   "provenance": []
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
