Spaces:
Runtime error
Runtime error
add colab_flask
Browse files- colab_flask.py +209 -0
colab_flask.py
ADDED
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
import cv2
|
4 |
+
from flask import Flask, request, jsonify, send_file
|
5 |
+
from flask_ngrok2 import run_with_ngrok
|
6 |
+
from pyngrok import ngrok
|
7 |
+
from subprocess import call
|
8 |
+
from tqdm import tqdm
|
9 |
+
import numpy as np
|
10 |
+
from ffmpy import FFmpeg
|
11 |
+
|
12 |
+
# !pip install flask flask-ngrok2 pyngrok
|
13 |
+
|
14 |
+
app = Flask(__name__)
|
15 |
+
auth_token = '2XQTtjJqVg4B4ryQVgauTPIGeiK_3JUWVJcMhXwpPxz2sc9KB'
|
16 |
+
root_dir = '/content/Wav2Lip-GFPGAN'
|
17 |
+
jobs_dir = os.path.join('/content', 'jobs')
|
18 |
+
|
19 |
+
|
20 |
+
@app.route('/', methods=['GET'])
|
21 |
+
def index():
|
22 |
+
return jsonify({'hello': 'world!'})
|
23 |
+
|
24 |
+
|
25 |
+
# New route to serve files from /content/input
|
26 |
+
@app.route('/job/<job_id>/<filename>', methods=['GET'])
|
27 |
+
def download_file(job_id, filename):
|
28 |
+
try:
|
29 |
+
file_path = os.path.join(jobs_dir, job_id, filename)
|
30 |
+
print(file_path)
|
31 |
+
return send_file(file_path, as_attachment=True)
|
32 |
+
except Exception as e:
|
33 |
+
return jsonify({'error': str(e)}), 500
|
34 |
+
|
35 |
+
|
36 |
+
@app.route('/wav2lip', methods=['POST'])
|
37 |
+
def wav2lip():
|
38 |
+
try:
|
39 |
+
# Get uploaded files
|
40 |
+
video_file = request.files['video']
|
41 |
+
audio_file = request.files['audio']
|
42 |
+
job_id = str(int(time.time()))
|
43 |
+
job_path = os.path.join(jobs_dir, job_id)
|
44 |
+
os.makedirs(job_path, exist_ok=True)
|
45 |
+
|
46 |
+
# Save the files to a temporary directory
|
47 |
+
video_path = os.path.join(job_path, video_file.filename)
|
48 |
+
audio_path = os.path.join(job_path, audio_file.filename)
|
49 |
+
video_file.save(video_path)
|
50 |
+
audio_file.save(audio_path)
|
51 |
+
|
52 |
+
wav2lip_mp4 = os.path.join(job_path, 'wav2lip.mp4')
|
53 |
+
call_wav2lip(video_path, audio_path, wav2lip_mp4)
|
54 |
+
|
55 |
+
output_filename = 'output.mp4'
|
56 |
+
output_mp4 = os.path.join(job_path, output_filename)
|
57 |
+
call_gfpgan(wav2lip_mp4, audio_path, output_mp4)
|
58 |
+
|
59 |
+
ngrok_url = ngrok.get_tunnels()[0].public_url
|
60 |
+
return jsonify({'url': f'{ngrok_url}/job/{job_id}/{output_filename}'})
|
61 |
+
|
62 |
+
except Exception as e:
|
63 |
+
return jsonify({'error': str(e)}), 500
|
64 |
+
|
65 |
+
|
66 |
+
def call_wav2lip(video_path, audio_path, output_path):
|
67 |
+
checkpoint_path = os.path.join(root_dir, 'wav2lip/checkpoints/wav2lip.pth')
|
68 |
+
assert os.path.isfile(video_path), f'Video path {video_path} not exist.'
|
69 |
+
assert os.path.isfile(audio_path), f'Audio path {audio_path} not exist.'
|
70 |
+
assert os.path.isfile(checkpoint_path), f'Checkpoint file {checkpoint_path} not exist.'
|
71 |
+
|
72 |
+
# python inference.py \
|
73 |
+
# --checkpoint_path checkpoints/wav2lip.pth \
|
74 |
+
# --face {inputVideoPath} \
|
75 |
+
# --audio {inputAudioPath} \
|
76 |
+
# --outfile {lipSyncedOutputPath}
|
77 |
+
cmd = [
|
78 |
+
"python",
|
79 |
+
"wav2lip/inference.py",
|
80 |
+
"--checkpoint_path", checkpoint_path,
|
81 |
+
# "--segmentation_path", "checkpoints/face_segmentation.pth",
|
82 |
+
"--face", video_path,
|
83 |
+
"--audio", audio_path,
|
84 |
+
"--outfile", output_path,
|
85 |
+
]
|
86 |
+
|
87 |
+
call(cmd)
|
88 |
+
return output_path
|
89 |
+
|
90 |
+
|
91 |
+
def _get_frames(video_path):
|
92 |
+
folder_path = os.path.dirname(video_path)
|
93 |
+
origin_frames_folder = os.path.join(folder_path, 'frames')
|
94 |
+
os.makedirs(origin_frames_folder, exist_ok=True)
|
95 |
+
|
96 |
+
# get frames pics
|
97 |
+
vidcap = cv2.VideoCapture(video_path)
|
98 |
+
numberOfFrames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
|
99 |
+
fps = vidcap.get(cv2.CAP_PROP_FPS)
|
100 |
+
print("FPS: ", fps, "Frames: ", numberOfFrames)
|
101 |
+
|
102 |
+
for frameNumber in tqdm(range(numberOfFrames)):
|
103 |
+
_, image = vidcap.read()
|
104 |
+
cv2.imwrite(os.path.join(origin_frames_folder, str(frameNumber).zfill(4) + '.jpg'), image)
|
105 |
+
return origin_frames_folder
|
106 |
+
|
107 |
+
|
108 |
+
def call_gfpgan(wav2lip_mp4, audio_path, output_mp4):
|
109 |
+
assert os.path.isfile(wav2lip_mp4), f'Video path {wav2lip_mp4} not exist.'
|
110 |
+
origin_frames_folder = _get_frames(wav2lip_mp4)
|
111 |
+
folder_path = os.path.dirname(wav2lip_mp4)
|
112 |
+
|
113 |
+
# python inference_gfpgan.py
|
114 |
+
# -i "$unProcessedFramesFolderPath"
|
115 |
+
# -o "$outputPath"
|
116 |
+
# -v 1.3
|
117 |
+
# -s 2
|
118 |
+
# --only_center_face
|
119 |
+
# --bg_upsampler None
|
120 |
+
cmd = [
|
121 |
+
"python",
|
122 |
+
"gfpgan/inference_gfpgan.py",
|
123 |
+
"-i", origin_frames_folder,
|
124 |
+
"-o", folder_path,
|
125 |
+
"-v", 1.3,
|
126 |
+
"-s", 2,
|
127 |
+
"--only_center_face",
|
128 |
+
"--bg_upsampler", None
|
129 |
+
]
|
130 |
+
call(cmd)
|
131 |
+
|
132 |
+
restoredFramesPath = os.path.join(folder_path, 'restored_imgs')
|
133 |
+
os.makedirs(restoredFramesPath, exist_ok=True)
|
134 |
+
folder_path = folder_path
|
135 |
+
dir_list = os.listdir(restoredFramesPath)
|
136 |
+
dir_list.sort()
|
137 |
+
batch = 0
|
138 |
+
batchSize = 300
|
139 |
+
for i in tqdm(range(0, len(dir_list), batchSize)):
|
140 |
+
img_array = []
|
141 |
+
start, end = i, i + batchSize
|
142 |
+
print("processing ", start, end)
|
143 |
+
for filename in tqdm(dir_list[start:end]):
|
144 |
+
filename = restoredFramesPath + filename;
|
145 |
+
img = cv2.imread(filename)
|
146 |
+
if img is None:
|
147 |
+
continue
|
148 |
+
height, width, layers = img.shape
|
149 |
+
size = (width, height)
|
150 |
+
img_array.append(img)
|
151 |
+
|
152 |
+
fourcc = cv2.VideoWriter_fourcc(*'X264')
|
153 |
+
filename = 'batch_' + str(batch).zfill(4) + '.mp4'
|
154 |
+
out = cv2.VideoWriter(os.path.join(folder_path, filename),
|
155 |
+
fourcc, 30, size)
|
156 |
+
batch = batch + 1
|
157 |
+
|
158 |
+
for i in range(len(img_array)):
|
159 |
+
out.write(img_array[i])
|
160 |
+
out.release()
|
161 |
+
|
162 |
+
concatTextFilePath = os.path.join(folder_path, "concat.txt")
|
163 |
+
|
164 |
+
concatTextFile = open(concatTextFilePath, "w")
|
165 |
+
for ips in range(batch):
|
166 |
+
concatTextFile.write("file batch_" + str(ips).zfill(4) + ".mp4\n")
|
167 |
+
concatTextFile.close()
|
168 |
+
|
169 |
+
concatedVideoOutputPath = os.path.join(folder_path, "concated_output.mp4")
|
170 |
+
ff = FFmpeg(
|
171 |
+
inputs={concatTextFilePath: None},
|
172 |
+
outputs={concatedVideoOutputPath: '-y -c copy'}
|
173 |
+
)
|
174 |
+
# !ffmpeg -y -f concat -i {concatTextFilePath} -c copy {concatedVideoOutputPath}
|
175 |
+
ff.run()
|
176 |
+
|
177 |
+
ff = FFmpeg(
|
178 |
+
inputs={concatedVideoOutputPath: None, audio_path: None},
|
179 |
+
outputs={output_mp4: '-y -map 0 -map 1:a -c:v libx264 -c:a aac -shortest'}
|
180 |
+
)
|
181 |
+
# !ffmpeg -y -i {concatedVideoOutputPath} -i {inputAudioPath} -map 0 -map 1:a -c:v copy -shortest {finalProcessedOuputVideo}
|
182 |
+
ff.run()
|
183 |
+
|
184 |
+
# from google.colab import files
|
185 |
+
# files.download(finalProcessedOuputVideo)
|
186 |
+
|
187 |
+
|
188 |
+
if __name__ == '__main__':
|
189 |
+
ngrok_url = run_with_ngrok(app, auth_token=auth_token).public_url # Start ngrok when the app is run
|
190 |
+
print(f" * Running on {ngrok_url}")
|
191 |
+
|
192 |
+
app.run()
|
193 |
+
|
194 |
+
|
195 |
+
def test():
|
196 |
+
# request
|
197 |
+
import requests
|
198 |
+
ngrok_url = f"http://74c0-34-87-172-60.ngrok-free.app"
|
199 |
+
url = f"{ngrok_url}/wav2lip"
|
200 |
+
print(url)
|
201 |
+
video_path = '/Users/taoluo/Downloads/oIy5B4-vHVw.4.6588496370531551262.0.jpg'
|
202 |
+
audio_path = '/Users/taoluo/Downloads/test_audio.mp3'
|
203 |
+
files = {'video': ('video.jpg', open(video_path, 'rb')), 'audio': ('audio.mp3', open(audio_path, 'rb'))}
|
204 |
+
headers = {'ngrok-skip-browser-warning': 'true'}
|
205 |
+
response = requests.post(url, files=files, headers=headers)
|
206 |
+
# Print the response
|
207 |
+
print(response.json())
|
208 |
+
data = response.json()
|
209 |
+
print(ngrok_url + data['url'])
|