toto10's picture
fc7e96b182b21f5be42d5060b4cc04b1c2e517067a0c471c97505b29f93f45e5
55f64b0
raw
history blame
7.98 kB
import os
import re
import subprocess
import glob
import shutil
import time
import cv2
import numpy as np
def clamp(n, smallest, largest):
return sorted([smallest, n, largest])[1]
def create_movie_from_frames( dir, start, end, number_of_digits, fps, output_path, export_type):
def get_export_str(export_type):
if export_type == "mp4":
return " -vcodec libx264 -pix_fmt yuv420p "
elif export_type == "webm":
# return " -vcodec vp9 -crf 10 -b:v 0 "
return " -crf 40 -b:v 0 -threads 4 "
elif export_type == "gif":
return " "
elif export_type == "rawvideo":
return " -vcodec rawvideo -pix_fmt bgr24 "
vframes = end - start + 1
path = os.path.join(dir , '%0' + str(number_of_digits) + 'd.png')
# ffmpeg -r 10 -start_number n -i snapshot_%03d.png -vframes 50 example.gif
subprocess.call("ffmpeg -framerate " + str(fps) + " -r " + str(fps) +
" -start_number " + str(start) +
" -i " + path +
" -vframes " + str( vframes ) +
get_export_str(export_type) +
output_path, shell=True)
def search_out_dirs(proj_dir, blend_rate):
### create out_dirs
p = re.compile(r'.*[\\\/]out\-([0-9]+)[\\\/]')
number_of_digits = -1
out_dirs=[]
for d in glob.glob( os.path.join(proj_dir ,"out-*/"), recursive=False):
m = p.fullmatch(d)
if m:
if number_of_digits == -1:
number_of_digits = len(m.group(1))
out_dirs.append({ 'keyframe':int(m.group(1)), 'path':d })
out_dirs = sorted(out_dirs, key=lambda x: x['keyframe'], reverse=True)
print(number_of_digits)
prev_key = -1
for out_d in out_dirs:
out_d['next_keyframe'] = prev_key
prev_key = out_d['keyframe']
out_dirs = sorted(out_dirs, key=lambda x: x['keyframe'])
### search start/end frame
prev_key = 0
for out_d in out_dirs:
imgs = sorted(glob.glob( os.path.join( out_d['path'], '[0-9]'*number_of_digits + '.png') ))
first_img = imgs[0]
print(first_img)
basename_without_ext = os.path.splitext(os.path.basename(first_img))[0]
blend_timing = (prev_key - out_d['keyframe'])*blend_rate + out_d['keyframe']
blend_timing = round(blend_timing)
start_frame = max( blend_timing, int(basename_without_ext) )
out_d['startframe'] = start_frame
last_img = imgs[-1]
print(last_img)
basename_without_ext = os.path.splitext(os.path.basename(last_img))[0]
end_frame = min( out_d['next_keyframe'], int(basename_without_ext) )
if end_frame == -1:
end_frame = int(basename_without_ext)
out_d['endframe'] = end_frame
prev_key = out_d['keyframe']
return number_of_digits, out_dirs
def get_ext(export_type):
if export_type in ("mp4","webm","gif"):
return "." + export_type
else:
return ".avi"
def trying_to_add_audio(original_movie_path, no_snd_movie_path, output_path, tmp_dir ):
if os.path.isfile(original_movie_path):
sound_path = os.path.join(tmp_dir , 'sound.mp4')
subprocess.call("ffmpeg -i " + original_movie_path + " -vn -acodec copy " + sound_path, shell=True)
if os.path.isfile(sound_path):
# ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
subprocess.call("ffmpeg -i " + no_snd_movie_path + " -i " + sound_path + " -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 " + output_path, shell=True)
return True
return False
def ebsynth_utility_stage7(dbg, project_args, blend_rate,export_type,is_invert_mask):
dbg.print("stage7")
dbg.print("")
project_dir, original_movie_path, _, _, _, _, _ = project_args
fps = 30
clip = cv2.VideoCapture(original_movie_path)
if clip:
fps = clip.get(cv2.CAP_PROP_FPS)
clip.release()
blend_rate = clamp(blend_rate, 0.0, 1.0)
dbg.print("blend_rate: {}".format(blend_rate))
dbg.print("export_type: {}".format(export_type))
dbg.print("fps: {}".format(fps))
if is_invert_mask:
project_dir = os.path.join( project_dir , "inv")
tmp_dir = os.path.join( project_dir , "crossfade_tmp")
if os.path.isdir(tmp_dir):
shutil.rmtree(tmp_dir)
os.mkdir(tmp_dir)
number_of_digits, out_dirs = search_out_dirs( project_dir, blend_rate )
if number_of_digits == -1:
dbg.print('no out dir')
return
### create frame imgs
start = out_dirs[0]['startframe']
end = out_dirs[-1]['endframe']
cur_clip = 0
next_clip = cur_clip+1 if len(out_dirs) > cur_clip+1 else -1
current_frame = 0
print(str(start) + " -> " + str(end+1))
black_img = np.zeros_like( cv2.imread( os.path.join(out_dirs[cur_clip]['path'], str(start).zfill(number_of_digits) + ".png") ) )
for i in range(start, end+1):
print(str(i) + " / " + str(end))
if next_clip == -1:
break
if i in range( out_dirs[cur_clip]['startframe'], out_dirs[cur_clip]['endframe'] +1):
pass
elif i in range( out_dirs[next_clip]['startframe'], out_dirs[next_clip]['endframe'] +1):
cur_clip = next_clip
next_clip = cur_clip+1 if len(out_dirs) > cur_clip+1 else -1
if next_clip == -1:
break
else:
### black
# front ... none
# back ... none
cv2.imwrite( os.path.join(tmp_dir, filename) , black_img)
current_frame = i
continue
filename = str(i).zfill(number_of_digits) + ".png"
# front ... cur_clip
# back ... next_clip or none
if i in range( out_dirs[next_clip]['startframe'], out_dirs[next_clip]['endframe'] +1):
# front ... cur_clip
# back ... next_clip
img_f = cv2.imread( os.path.join(out_dirs[cur_clip]['path'] , filename) )
img_b = cv2.imread( os.path.join(out_dirs[next_clip]['path'] , filename) )
back_rate = (i - out_dirs[next_clip]['startframe'])/ max( 1 , (out_dirs[cur_clip]['endframe'] - out_dirs[next_clip]['startframe']) )
img = cv2.addWeighted(img_f, 1.0 - back_rate, img_b, back_rate, 0)
cv2.imwrite( os.path.join(tmp_dir , filename) , img)
else:
# front ... cur_clip
# back ... none
filename = str(i).zfill(number_of_digits) + ".png"
shutil.copy( os.path.join(out_dirs[cur_clip]['path'] , filename) , os.path.join(tmp_dir , filename) )
current_frame = i
start2 = current_frame+1
print(str(start2) + " -> " + str(end+1))
for i in range(start2, end+1):
filename = str(i).zfill(number_of_digits) + ".png"
shutil.copy( os.path.join(out_dirs[cur_clip]['path'] , filename) , os.path.join(tmp_dir , filename) )
### create movie
movie_base_name = time.strftime("%Y%m%d-%H%M%S")
if is_invert_mask:
movie_base_name = "inv_" + movie_base_name
nosnd_path = os.path.join(project_dir , movie_base_name + get_ext(export_type))
start = out_dirs[0]['startframe']
end = out_dirs[-1]['endframe']
create_movie_from_frames( tmp_dir, start, end, number_of_digits, fps, nosnd_path, export_type)
dbg.print("exported : " + nosnd_path)
if export_type == "mp4":
with_snd_path = os.path.join(project_dir , movie_base_name + '_with_snd.mp4')
if trying_to_add_audio(original_movie_path, nosnd_path, with_snd_path, tmp_dir):
dbg.print("exported : " + with_snd_path)
dbg.print("")
dbg.print("completed.")