lorneluo commited on
Commit
61ba537
1 Parent(s): f8a221c

run.py to download video audio and process

Browse files
Files changed (5) hide show
  1. colab_flask.py +26 -94
  2. gfpgan/inference_gfpgan.py +1 -1
  3. main.py +124 -26
  4. merge.py +1 -1
  5. run.py +51 -0
colab_flask.py CHANGED
@@ -2,7 +2,9 @@ import os
2
  import subprocess
3
  import time
4
  from datetime import datetime
5
-
 
 
6
  import cv2
7
  from flask import Flask, request, jsonify, send_file
8
  from flask_ngrok2 import run_with_ngrok
@@ -11,6 +13,8 @@ from tqdm import tqdm
11
  import numpy as np
12
  from ffmpy import FFmpeg
13
 
 
 
14
  # !pip install flask flask-ngrok2 pyngrok
15
 
16
  app = Flask(__name__)
@@ -58,105 +62,33 @@ def wav2lip():
58
  output_mp4 = os.path.join(job_path, output_filename)
59
  call_gfpgan(wav2lip_mp4, audio_path, output_mp4)
60
 
 
 
 
 
61
  return jsonify({'url': f'/job/{job_id}/{output_filename}'})
62
 
63
  except Exception as e:
64
  return jsonify({'error': str(e)}), 500
65
 
66
 
67
- def call_wav2lip(video_path, audio_path, output_path):
68
- checkpoint_path = os.path.join(root_dir, 'wav2lip/checkpoints/wav2lip.pth')
69
- assert os.path.isfile(video_path), f'Video path {video_path} not exist.'
70
- assert os.path.isfile(audio_path), f'Audio path {audio_path} not exist.'
71
- assert os.path.isfile(checkpoint_path), f'Checkpoint file {checkpoint_path} not exist.'
72
-
73
- # python inference.py \
74
- # --checkpoint_path checkpoints/wav2lip.pth \
75
- # --face {inputVideoPath} \
76
- # --audio {inputAudioPath} \
77
- # --outfile {lipSyncedOutputPath}
78
- start = datetime.now()
79
- cmd = [
80
- "python",
81
- "wav2lip/inference.py",
82
- "--checkpoint_path", checkpoint_path, #
83
- # "--segmentation_path", "checkpoints/face_segmentation.pth",
84
- "--face", video_path,
85
- "--audio", audio_path,
86
- "--outfile", output_path,
87
- ]
88
- print(f'Call subprocess: {cmd}')
89
- proc = subprocess.Popen(cmd, shell=False)
90
- proc.communicate()
91
- duration = datetime.now() - start
92
- print(f'wav2lip finished in {duration}')
93
- return output_path
94
-
95
-
96
- def _get_frames(video_path):
97
- folder_path = os.path.dirname(video_path)
98
- origin_frames_folder = os.path.join(folder_path, 'frames')
99
- os.makedirs(origin_frames_folder, exist_ok=True)
100
-
101
- # get frames pics
102
- vidcap = cv2.VideoCapture(video_path)
103
- numberOfFrames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
104
- fps = vidcap.get(cv2.CAP_PROP_FPS)
105
- print("FPS: ", fps, "Frames: ", numberOfFrames)
106
-
107
- for frameNumber in tqdm(range(numberOfFrames)):
108
- _, image = vidcap.read()
109
- cv2.imwrite(os.path.join(origin_frames_folder, str(frameNumber).zfill(4) + '.jpg'), image)
110
- return origin_frames_folder
111
-
112
-
113
- def call_gfpgan(wav2lip_mp4, audio_path, output_mp4):
114
- assert os.path.isfile(wav2lip_mp4), f'Video path {wav2lip_mp4} not exist.'
115
- origin_frames_folder = _get_frames(wav2lip_mp4)
116
- folder_path = os.path.dirname(wav2lip_mp4)
117
-
118
- # python inference_gfpgan.py
119
- # -i "$unProcessedFramesFolderPath"
120
- # -o "$outputPath"
121
- # -v 1.3
122
- # -s 2
123
- # --only_center_face
124
- # --bg_upsampler None
125
- start = datetime.now()
126
- cmd = [
127
- "python",
128
- "gfpgan/inference_gfpgan.py",
129
- "-i", origin_frames_folder,
130
- "-o", folder_path,
131
- # "-v", str(1.4),
132
- # "-s", str(2),
133
- "--only_center_face",
134
- "--bg_upsampler", 'realesrgan'
135
- ]
136
- print(cmd)
137
- proc = subprocess.Popen(cmd, shell=True)
138
- proc.communicate()
139
- duration = datetime.now() - start
140
- print(f'inference_gfpgan finished in {duration}')
141
-
142
- start = datetime.now()
143
- cmd = [
144
- "python",
145
- "merge.py",
146
- "-j", folder_path,
147
- "-a", audio_path,
148
- "-o", output_mp4,
149
- ]
150
- proc = subprocess.Popen(cmd, shell=True)
151
- proc.communicate()
152
- duration = datetime.now() - start
153
- print(f'Merge output in {duration}')
154
- print(output_mp4)
155
-
156
- # from google.colab import files
157
- # files.download(finalProcessedOuputVideo)
158
-
159
-
160
  if __name__ == '__main__':
161
  run_with_ngrok(app, auth_token=auth_token)
162
  app.run()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import subprocess
3
  import time
4
  from datetime import datetime
5
+ from functools import partial
6
+ from concurrent.futures import ThreadPoolExecutor
7
+ from collections import deque
8
  import cv2
9
  from flask import Flask, request, jsonify, send_file
10
  from flask_ngrok2 import run_with_ngrok
 
13
  import numpy as np
14
  from ffmpy import FFmpeg
15
 
16
+ from main import call_wav2lip, call_gfpgan, merge
17
+
18
  # !pip install flask flask-ngrok2 pyngrok
19
 
20
  app = Flask(__name__)
 
62
  output_mp4 = os.path.join(job_path, output_filename)
63
  call_gfpgan(wav2lip_mp4, audio_path, output_mp4)
64
 
65
+ output_filename = 'output.mp4'
66
+ output_mp4 = os.path.join(job_path, output_filename)
67
+ merge(job_path, audio_path, output_mp4)
68
+
69
  return jsonify({'url': f'/job/{job_id}/{output_filename}'})
70
 
71
  except Exception as e:
72
  return jsonify({'error': str(e)}), 500
73
 
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  if __name__ == '__main__':
76
  run_with_ngrok(app, auth_token=auth_token)
77
  app.run()
78
+
79
+
80
+ def test():
81
+ # request
82
+ import requests
83
+ ngrok_url = f"http://74c0-34-87-172-60.ngrok-free.app"
84
+ url = f"{ngrok_url}/wav2lip"
85
+ print(url)
86
+ video_path = '/Users/taoluo/Downloads/oIy5B4-vHVw.4.6588496370531551262.0.jpg'
87
+ audio_path = '/Users/taoluo/Downloads/test_audio.mp3'
88
+ files = {'video': ('video.jpg', open(video_path, 'rb')), 'audio': ('audio.mp3', open(audio_path, 'rb'))}
89
+ headers = {'ngrok-skip-browser-warning': 'true'}
90
+ response = requests.post(url, files=files, headers=headers)
91
+ # Print the response
92
+ print(response.json())
93
+ data = response.json()
94
+ print(ngrok_url + data['url'])
gfpgan/inference_gfpgan.py CHANGED
@@ -117,7 +117,7 @@ def main():
117
  for img_path in tqdm(img_list):
118
  # read image
119
  img_name = os.path.basename(img_path)
120
- print(f'Processing {img_name} ...')
121
  basename, ext = os.path.splitext(img_name)
122
  input_img = cv2.imread(img_path, cv2.IMREAD_COLOR)
123
 
 
117
  for img_path in tqdm(img_list):
118
  # read image
119
  img_name = os.path.basename(img_path)
120
+ # print(f'Processing {img_name} ...')
121
  basename, ext = os.path.splitext(img_name)
122
  input_img = cv2.imread(img_path, cv2.IMREAD_COLOR)
123
 
main.py CHANGED
@@ -1,27 +1,125 @@
1
  import os
2
- from argparse import Namespace
3
- from
4
- basePath = os.path.dirname(os.path.realpath(__file__))
5
- wav2lipFolderName = 'wav2lip'
6
- gfpganFolderName = 'gfpgan'
7
- wav2lipPath = os.path.join(basePath, wav2lipFolderName)
8
- gfpganPath = os.path.join(basePath, gfpganFolderName)
9
-
10
- outputPath = basePath + '/outputs'
11
- inputAudioPath = basePath + '/inputs/kim_audio.mp3'
12
- inputVideoPath = basePath + '/inputs/kimk_7s_raw.mp4'
13
- lipSyncedOutputPath = basePath + '/outputs/result.mp4'
14
- if not os.path.exists(outputPath):
15
- os.makedirs(outputPath)
16
-
17
- if __name__ == '__main__':
18
- args = Namespace(checkpoint_path='checkpoints/wav2lip.pth',
19
- face=inputVideoPath,
20
- audio=inputAudioPath,
21
- outfile='results/result_voice.mp4',
22
- static=False,
23
- fps=25.0, pads=[0, 10, 0, 0], face_det_batch_size=16, wav2lip_batch_size=128, resize_factor=1,
24
- crop=[0, -1, 0, -1], box=[-1, -1, -1, -1], rotate=False, nosmooth=False, img_size=96)
25
-
26
- print(inputAudioPath, os.path.isdir(inputAudioPath))
27
- print(inputVideoPath, os.path.isdir(inputVideoPath))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import subprocess
3
+ import cv2
4
+ from datetime import datetime
5
+ from functools import partial
6
+ from concurrent.futures import ThreadPoolExecutor
7
+ from collections import deque
8
+ from tqdm import tqdm
9
+
10
+ root_dir = '/content/wav2lip-gfpgan'
11
+
12
+
13
+ def stream_command(
14
+ args,
15
+ *,
16
+ stdout_handler=print,
17
+ stderr_handler=print,
18
+ check=True,
19
+ text=True,
20
+ stdout=subprocess.PIPE,
21
+ stderr=subprocess.PIPE,
22
+ **kwargs,
23
+ ):
24
+ """Mimic subprocess.run, while processing the command output in real time."""
25
+ with subprocess.Popen(args, text=text, stdout=stdout, stderr=stderr, **kwargs) as process:
26
+ with ThreadPoolExecutor(2) as pool: # two threads to handle the streams
27
+ exhaust = partial(pool.submit, partial(deque, maxlen=0))
28
+ exhaust(stdout_handler(line[:-1]) for line in process.stdout)
29
+ exhaust(stderr_handler(line[:-1]) for line in process.stderr)
30
+ retcode = process.poll()
31
+ if check and retcode:
32
+ raise subprocess.CalledProcessError(retcode, process.args)
33
+ return subprocess.CompletedProcess(process.args, retcode)
34
+
35
+
36
+ def call_wav2lip(video_path, audio_path, output_path):
37
+ checkpoint_path = os.path.join(root_dir, 'wav2lip/checkpoints/wav2lip.pth')
38
+ assert os.path.isfile(video_path), f'Video path {video_path} not exist.'
39
+ assert os.path.isfile(audio_path), f'Audio path {audio_path} not exist.'
40
+ assert os.path.isfile(checkpoint_path), f'Checkpoint file {checkpoint_path} not exist.'
41
+
42
+ # python inference.py \
43
+ # --checkpoint_path checkpoints/wav2lip.pth \
44
+ # --face {inputVideoPath} \
45
+ # --audio {inputAudioPath} \
46
+ # --outfile {lipSyncedOutputPath}
47
+ start = datetime.now()
48
+ cmd = [
49
+ "python",
50
+ "wav2lip/inference.py",
51
+ "--checkpoint_path", checkpoint_path, #
52
+ # "--segmentation_path", "checkpoints/face_segmentation.pth",
53
+ "--face", video_path,
54
+ "--audio", audio_path,
55
+ "--outfile", output_path,
56
+ ]
57
+
58
+ print(f'Call subprocess: {cmd}')
59
+ stream_command(cmd)
60
+ duration = datetime.now() - start
61
+ print(f'wav2lip finished in {duration}')
62
+ origin_frames_folder = _get_frames(output_path)
63
+ return output_path
64
+
65
+
66
+ def _get_frames(video_path):
67
+ folder_path = os.path.dirname(video_path)
68
+ origin_frames_folder = os.path.join(folder_path, 'frames')
69
+ os.makedirs(origin_frames_folder, exist_ok=True)
70
+
71
+ # get frames pics
72
+ vidcap = cv2.VideoCapture(video_path)
73
+ numberOfFrames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
74
+ fps = vidcap.get(cv2.CAP_PROP_FPS)
75
+ print("FPS: ", fps, "Frames: ", numberOfFrames)
76
+
77
+ for frameNumber in tqdm(range(numberOfFrames)):
78
+ _, image = vidcap.read()
79
+ cv2.imwrite(os.path.join(origin_frames_folder, str(frameNumber).zfill(4) + '.jpg'), image)
80
+ return origin_frames_folder
81
+
82
+
83
+ def call_gfpgan(wav2lip_mp4):
84
+ assert os.path.isfile(wav2lip_mp4), f'Video path {wav2lip_mp4} not exist.'
85
+ folder_path = os.path.dirname(wav2lip_mp4)
86
+ origin_frames_folder = os.path.join(folder_path, 'frames')
87
+
88
+ # python inference_gfpgan.py
89
+ # -i "$unProcessedFramesFolderPath"
90
+ # -o "$outputPath"
91
+ # -v 1.3
92
+ # -s 2
93
+ # --only_center_face
94
+ # --bg_upsampler None
95
+ start = datetime.now()
96
+ cmd = [
97
+ "python",
98
+ "gfpgan/inference_gfpgan.py",
99
+ "-i", origin_frames_folder,
100
+ "-o", folder_path,
101
+ # "-v", str(1.4),
102
+ # "-s", str(2),
103
+ "--only_center_face",
104
+ "--bg_upsampler", 'realesrgan'
105
+ ]
106
+ print(cmd)
107
+ stream_command(cmd)
108
+ duration = datetime.now() - start
109
+ print(f'inference_gfpgan finished in {duration}')
110
+
111
+
112
+ def merge(folder_path, audio_path, output_mp4):
113
+ start = datetime.now()
114
+ cmd = [
115
+ "python",
116
+ "merge.py",
117
+ "-j", folder_path,
118
+ "-a", audio_path,
119
+ "-o", output_mp4,
120
+ ]
121
+ stream_command(cmd)
122
+ duration = datetime.now() - start
123
+ print(f'Merge output in {duration}')
124
+ print(output_mp4)
125
+
merge.py CHANGED
@@ -73,5 +73,5 @@ if __name__ == '__main__':
73
  parser.add_argument('-a', '--audio', type=str, help='audio file path')
74
  parser.add_argument('-o', '--output', type=str, help='output file path')
75
  args = parser.parse_args()
76
-
77
  cli(args)
 
73
  parser.add_argument('-a', '--audio', type=str, help='audio file path')
74
  parser.add_argument('-o', '--output', type=str, help='output file path')
75
  args = parser.parse_args()
76
+
77
  cli(args)
run.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from urllib.request import urlretrieve
4
+
5
+ from main import call_wav2lip, call_gfpgan, merge
6
+
7
+ root_dir = '/content/jobs'
8
+ os.makedirs(root_dir,exist_ok=True)
9
+
10
+
11
+ def main(job_id, video_url, audio_url):
12
+ job_path = os.path.join(root_dir, job_id)
13
+ os.makedirs(job_path, exist_ok=True)
14
+
15
+ if video_url.startswith('http'):
16
+ video_file = os.path.basename(video_url)
17
+ video_path = os.path.join(job_path, video_file)
18
+ urlretrieve(video_url, video_path)
19
+ else:
20
+ video_path = video_url
21
+
22
+ if audio_url.startswith('http'):
23
+ audio_file = os.path.basename(audio_url)
24
+ audio_path = os.path.join(job_path, audio_file)
25
+ urlretrieve(audio_url, audio_path)
26
+ else:
27
+ audio_path = audio_url
28
+
29
+ assert os.path.isfile(video_path), f'Video {video_path} not exist.'
30
+ assert os.path.isfile(audio_path), f'Audio {audio_path} not exist.'
31
+
32
+ wav2lip_mp4 = os.path.join(job_path, 'wav2lip.mp4')
33
+ call_wav2lip(video_path, audio_path, wav2lip_mp4)
34
+ call_gfpgan(wav2lip_mp4)
35
+
36
+ output_filename = 'output.mp4'
37
+ output_mp4 = os.path.join(job_path, output_filename)
38
+ merge(job_path, audio_path, output_mp4)
39
+ return output_mp4
40
+
41
+
42
+ if __name__ == '__main__':
43
+ job_id = sys.argv[1]
44
+ video_url = sys.argv[2]
45
+ audio_url = sys.argv[3]
46
+
47
+ output_mp4 = main(job_id, video_url, audio_url)
48
+
49
+ from google.colab import files
50
+
51
+ files.download(output_mp4)