{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Wav2Lip.ipynb",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU",
    "gpuClass": "standard"
  },
  "cells": [
    {
      "cell_type": "code",
      "source": [
        "!git clone https://github.com/ajay-sainy/Wav2Lip-GFPGAN.git\n",
        "basePath = \"/content/Wav2Lip-GFPGAN\"\n",
        "%cd {basePath}"
      ],
      "metadata": {
        "id": "YhFe3CJGAIiV"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "wav2lipFolderName = 'Wav2Lip-master'\n",
        "gfpganFolderName = 'GFPGAN-master'\n",
        "wav2lipPath = basePath + '/' + wav2lipFolderName\n",
        "gfpganPath = basePath + '/' + gfpganFolderName\n",
        "\n",
        "!wget 'https://www.adrianbulat.com/downloads/python-fan/s3fd-619a316812.pth' -O {wav2lipPath}'/face_detection/detection/sfd/s3fd.pth'\n",
        "!gdown https://drive.google.com/uc?id=1fQtBSYEyuai9MjBOF8j7zZ4oQ9W2N64q --output {wav2lipPath}'/checkpoints/'"
      ],
      "metadata": {
        "id": "mH7A_OaFUs8U"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!pip install -r requirements.txt"
      ],
      "metadata": {
        "id": "CAJqWQS17Qk1"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "EqX_2YtkUjRI"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "outputPath = basePath+'/outputs'\n",
        "inputAudioPath = basePath + '/inputs/kim_audio.mp3'\n",
        "inputVideoPath = basePath + '/inputs/kimk_7s_raw.mp4'\n",
        "lipSyncedOutputPath = basePath + '/outputs/result.mp4'\n",
        "\n",
        "if not os.path.exists(outputPath):\n",
        "  os.makedirs(outputPath)\n",
        "\n",
        "!cd $wav2lipFolderName && python inference.py \\\n",
        "--checkpoint_path checkpoints/wav2lip.pth \\\n",
        "--face {inputVideoPath} \\\n",
        "--audio {inputAudioPath} \\\n",
        "--outfile {lipSyncedOutputPath}"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "!cd $gfpganFolderName && python setup.py develop\n",
        "!wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth -P {gfpganFolderName}'/experiments/pretrained_models'"
      ],
      "metadata": {
        "id": "PPBew5FGGvP9"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "import cv2\n",
        "from tqdm import tqdm\n",
        "from os import path\n",
        "\n",
        "import os\n",
        "\n",
        "inputVideoPath = outputPath+'/result.mp4'\n",
        "unProcessedFramesFolderPath = outputPath+'/frames'\n",
        "\n",
        "if not os.path.exists(unProcessedFramesFolderPath):\n",
        "  os.makedirs(unProcessedFramesFolderPath)\n",
        "\n",
        "vidcap = cv2.VideoCapture(inputVideoPath)\n",
        "numberOfFrames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))\n",
        "fps = vidcap.get(cv2.CAP_PROP_FPS)\n",
        "print(\"FPS: \", fps, \"Frames: \", numberOfFrames)\n",
        "\n",
        "for frameNumber in tqdm(range(numberOfFrames)):\n",
        "    _,image = vidcap.read()\n",
        "    cv2.imwrite(path.join(unProcessedFramesFolderPath, str(frameNumber).zfill(4)+'.jpg'), image)\n"
      ],
      "metadata": {
        "id": "X_RNegAcISU2"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!cd $gfpganFolderName && \\\n",
        "  python inference_gfpgan.py -i $unProcessedFramesFolderPath -o $outputPath -v 1.3 -s 2 --only_center_face --bg_upsampler None"
      ],
      "metadata": {
        "id": "k6krjfxTJYlu"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "import os\n",
        "restoredFramesPath = outputPath + '/restored_imgs/'\n",
        "processedVideoOutputPath = outputPath\n",
        "\n",
        "dir_list = os.listdir(restoredFramesPath)\n",
        "dir_list.sort()\n",
        "\n",
        "import cv2\n",
        "import numpy as np\n",
        "\n",
        "batch = 0\n",
        "batchSize = 300\n",
        "from tqdm import tqdm\n",
        "for i in tqdm(range(0, len(dir_list), batchSize)):\n",
        "  img_array = []\n",
        "  start, end = i, i+batchSize\n",
        "  print(\"processing \", start, end)\n",
        "  for filename in  tqdm(dir_list[start:end]):\n",
        "      filename = restoredFramesPath+filename;\n",
        "      img = cv2.imread(filename)\n",
        "      if img is None:\n",
        "        continue\n",
        "      height, width, layers = img.shape\n",
        "      size = (width,height)\n",
        "      img_array.append(img)\n",
        "\n",
        "\n",
        "  out = cv2.VideoWriter(processedVideoOutputPath+'/batch_'+str(batch).zfill(4)+'.avi',cv2.VideoWriter_fourcc(*'DIVX'), 30, size)\n",
        "  batch = batch + 1\n",
        " \n",
        "  for i in range(len(img_array)):\n",
        "    out.write(img_array[i])\n",
        "  out.release()\n"
      ],
      "metadata": {
        "id": "XibzGPIVJfvP"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "concatTextFilePath = outputPath + \"/concat.txt\"\n",
        "concatTextFile=open(concatTextFilePath,\"w\")\n",
        "for ips in range(batch):\n",
        "  concatTextFile.write(\"file batch_\" + str(ips).zfill(4) + \".avi\\n\")\n",
        "concatTextFile.close()\n",
        "\n",
        "concatedVideoOutputPath = outputPath + \"/concated_output.avi\"\n",
        "!ffmpeg -y -f concat -i {concatTextFilePath} -c copy {concatedVideoOutputPath} \n",
        "\n",
        "finalProcessedOuputVideo = processedVideoOutputPath+'/final_with_audio.avi'\n",
        "!ffmpeg -y -i {concatedVideoOutputPath} -i {inputAudioPath} -map 0 -map 1:a -c:v copy -shortest {finalProcessedOuputVideo}\n",
        "\n",
        "from google.colab import files\n",
        "files.download(finalProcessedOuputVideo)"
      ],
      "metadata": {
        "id": "jtde28qwpDd6"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}