def generate_print_poster(_print): pic_dir = f'{_print.printer.id}/{_print.id}' print_pics = list_dir(f'raw/{pic_dir}/', settings.PICS_CONTAINER, long_term_storage=False) if not print_pics: return print_pics.sort() to_dir = os.path.join(tempfile.gettempdir(), str(_print.id)) shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) unrotated_jpg = os.path.join(to_dir, 'ss.jpg') with open(unrotated_jpg, 'wb') as file_obj: retrieve_to_file_obj(print_pics[-1], file_obj, settings.PICS_CONTAINER, long_term_storage=False) with open(unrotated_jpg, 'rb') as unrotated_jpg_file: _, ss_url = save_file_obj(f'raw/{_print.printer.id}/ss.jpg', unrotated_jpg_file, settings.PICS_CONTAINER, long_term_storage=False) redis.printer_pic_set(_print.printer.id, {'img_url': ss_url}, ex=IMG_URL_TTL_SECONDS) ffmpeg_extra_options = orientation_to_ffmpeg_options( _print.printer.settings) rotated_jpg = os.path.join(to_dir, 'rotated.jpg') cmd = f'ffmpeg -y -i {unrotated_jpg} {ffmpeg_extra_options} {rotated_jpg}' subprocess.run(cmd.split(), check=True) with open(rotated_jpg, 'rb') as poster_file: _, poster_file_url = save_file_obj( 'private/{}_poster.jpg'.format(_print.id), poster_file, settings.TIMELAPSE_CONTAINER) _print.poster_url = poster_file_url _print.save() shutil.rmtree(to_dir, ignore_errors=True)
def compile_timelapse(print_id): _print = Print.objects.select_related('printer').get(id=print_id) to_dir = os.path.join(tempfile.gettempdir(), 'tl_' + str(_print.id)) shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) ffmpeg_extra_options = orientation_to_ffmpeg_options( _print.printer.settings) pic_dir = f'{_print.printer.id}/{_print.id}' print_pics = list_dir(f'raw/{pic_dir}/', settings.PICS_CONTAINER, long_term_storage=False) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) mp4_filename = '{}.mp4'.format(_print.id) output_mp4 = os.path.join(to_dir, mp4_filename) cmd = 'ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p {} {}'.format( local_pics[-1].parent, ffmpeg_extra_options, output_mp4) subprocess.run(cmd.split(), check=True) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) _print.video_url = mp4_file_url _print.save() # build tagged timelapse print_pics = list_dir(f'tagged/{pic_dir}/', settings.PICS_CONTAINER, long_term_storage=False) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) mp4_filename = '{}_tagged.mp4'.format(_print.id) output_mp4 = os.path.join(to_dir, mp4_filename) cmd = 'ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p -vf pad=ceil(iw/2)*2:ceil(ih/2)*2 {} {}'.format( local_pics[0].parent, ffmpeg_extra_options, output_mp4) subprocess.run(cmd.split(), check=True) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) json_files = list_dir(f'p/{pic_dir}/', settings.PICS_CONTAINER, long_term_storage=False) local_jsons = download_files(json_files, to_dir) prediction_json = [] num_missing_p_json = 0 for pic_path in local_pics: try: with open( str(pic_path).replace('tagged/', 'p/').replace('.jpg', '.json'), 'r') as f: p_json = json.load(f) except ( FileNotFoundError, json.decoder.JSONDecodeError ) as e: # In case there is no corresponding json, the file will be empty and JSONDecodeError will be thrown LOGGER.warn(e) p_json = [{}] num_missing_p_json += 1 if num_missing_p_json > 5: raise Exception('Too many missing p_json files.') prediction_json += p_json prediction_json_io = io.BytesIO() prediction_json_io.write(json.dumps(prediction_json).encode('UTF-8')) prediction_json_io.seek(0) _, json_url = save_file_obj('private/{}_p.json'.format(_print.id), prediction_json_io, settings.TIMELAPSE_CONTAINER) _print.tagged_video_url = mp4_file_url _print.prediction_json_url = json_url _print.save() shutil.rmtree(to_dir, ignore_errors=True) clean_up_print_pics(_print)
def compile_timelapse(print_id): _print = Print.objects.select_related('printer').get(id=print_id) to_dir = os.path.join(tempfile.gettempdir(), str(_print.id)) shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) ffmpeg_extra_options = orientation_to_ffmpeg_options(_print.printer.settings) print_pics = filter_pics_by_start_end(list_file_obj('raw/{}/'.format(_print.printer.id), settings.PICS_CONTAINER), _print.started_at, _print.ended_at()) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) mp4_filename = '{}.mp4'.format(_print.id) output_mp4 = os.path.join(to_dir, mp4_filename) cmd = 'ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p {} {}'.format(local_pics[-1].parent, ffmpeg_extra_options, output_mp4) subprocess.run(cmd.split(), check=True) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) last_pic = os.path.join(to_dir, 'ss.jpg') # https://superuser.com/questions/1448665/ffmpeg-how-to-get-last-frame-from-a-video subprocess.run('ffmpeg -y -i {} -sseof -1 -update 1 -vframes 1 -q:v 2 {}'.format(output_mp4, last_pic).split(' '), check=True) with open(last_pic, 'rb') as poster_file: _, poster_file_url = save_file_obj('private/{}_poster.jpg'.format(_print.id), poster_file, settings.TIMELAPSE_CONTAINER) _print.video_url = mp4_file_url _print.poster_url = poster_file_url _print.save() # build tagged timelapse print_pics = filter_pics_by_start_end(list_file_obj('tagged/{}/'.format(_print.printer.id), settings.PICS_CONTAINER), _print.started_at, _print.ended_at()) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) mp4_filename = '{}_tagged.mp4'.format(_print.id) output_mp4 = os.path.join(to_dir, mp4_filename) cmd = 'ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p {} {}'.format(local_pics[0].parent, ffmpeg_extra_options, output_mp4) subprocess.run(cmd.split(), check=True) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) preidction_json = [] for print_pic_filename in print_pics: try: m = re.search('tagged/(\d+)/(\d+).jpg', print_pic_filename) p_json = json.loads(redis.printer_p_json_get(m[1], m[2])) except (json.decoder.JSONDecodeError, TypeError): # In case there is no corresponding json, the file will be empty and JSONDecodeError will be thrown p_json = [{}] preidction_json += p_json preidction_json_io = io.BytesIO() preidction_json_io.write(json.dumps(preidction_json).encode('UTF-8')) preidction_json_io.seek(0) _, json_url = save_file_obj('private/{}_p.json'.format(_print.id), preidction_json_io, settings.TIMELAPSE_CONTAINER) _print.tagged_video_url = mp4_file_url _print.prediction_json_url = json_url _print.save() shutil.rmtree(to_dir, ignore_errors=True)
def compile_timelapse(print_id): _print = Print.objects.select_related('printer').get(id=print_id) to_dir = os.path.join(tempfile.gettempdir(), str(_print.id)) shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) ffmpeg_extra_options = orientation_to_ffmpeg_options( _print.printer.settings) pic_dir = f'{_print.printer.id}/{_print.id}' print_pics = list_dir(f'raw/{pic_dir}/', settings.PICS_CONTAINER, long_term_storage=False) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) mp4_filename = '{}.mp4'.format(_print.id) output_mp4 = os.path.join(to_dir, mp4_filename) cmd = 'ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p {} {}'.format( local_pics[-1].parent, ffmpeg_extra_options, output_mp4) subprocess.run(cmd.split(), check=True) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) _print.video_url = mp4_file_url _print.save() # build tagged timelapse print_pics = list_dir(f'tagged/{pic_dir}/', settings.PICS_CONTAINER, long_term_storage=False) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) mp4_filename = '{}_tagged.mp4'.format(_print.id) output_mp4 = os.path.join(to_dir, mp4_filename) cmd = 'ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p -vf pad=ceil(iw/2)*2:ceil(ih/2)*2 {} {}'.format( local_pics[0].parent, ffmpeg_extra_options, output_mp4) subprocess.run(cmd.split(), check=True) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) preidction_json = [] for print_pic_filename in print_pics: try: m = re.search('tagged/(\d+)/\d+/([\d.]+).jpg', print_pic_filename) p_json = json.loads(redis.printer_p_json_get(m[1], m[2])) except ( json.decoder.JSONDecodeError, TypeError ): # In case there is no corresponding json, the file will be empty and JSONDecodeError will be thrown p_json = [{}] preidction_json += p_json preidction_json_io = io.BytesIO() preidction_json_io.write(json.dumps(preidction_json).encode('UTF-8')) preidction_json_io.seek(0) _, json_url = save_file_obj('private/{}_p.json'.format(_print.id), preidction_json_io, settings.TIMELAPSE_CONTAINER) _print.tagged_video_url = mp4_file_url _print.prediction_json_url = json_url _print.save() shutil.rmtree(to_dir, ignore_errors=True) clean_up_print_pics(_print)