def compile_timelapse(self, print_id): print = Print.objects.get(id=print_id) end_time = print.finished_at or print.cancelled_at if (end_time - print.started_at).total_seconds() < settings.TIMELAPSE_MINIMUM_SECONDS: print.delete() return to_dir = os.path.join(tempfile.gettempdir(), str(print.id)) shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) print_pics = filter_pics_by_start_end(list_file_obj('raw/{}/'.format(print.printer.id), settings.PICS_CONTAINER), print.started_at, end_time) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) last_pic = local_pics[-1] mp4_filename = '{}.mp4'.format(print.id) output_mp4 = os.path.join(to_dir, mp4_filename) subprocess.run('ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p {}'.format(last_pic.parent, output_mp4).split(' '), check=True) shutil.copyfile(last_pic, os.path.join(to_dir, '{}.jpg'.format(print.id))) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) 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, end_time) 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) subprocess.run('ffmpeg -y -r 30 -pattern_type glob -i {}/*.jpg -c:v libx264 -pix_fmt yuv420p {}'.format(local_pics[0].parent, output_mp4).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) 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(self, print_id): pprint = Print.objects.get(id=print_id) end_time = pprint.finished_at or pprint.cancelled_at to_dir = os.path.join(tempfile.gettempdir(), str(pprint.id)) shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) print_pics = filter_pics_by_start_end( list_file_obj('raw/{}/'.format(pprint.printer.id), settings.PICS_CONTAINER), pprint.started_at, end_time) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) last_pic = local_pics[-1] mp4_filename = '{}.mp4'.format(pprint.id) output_mp4 = os.path.join(to_dir, mp4_filename) subprocess.run( 'ffmpeg -y -pattern_type glob -i {}/*.jpg -c:v libx264 -vf fps=30 -pix_fmt yuv420p {}' .format(last_pic.parent, output_mp4).split(' '), check=True) shutil.copyfile(last_pic, os.path.join(to_dir, '{}.jpg'.format(pprint.id))) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj('private/{}'.format(mp4_filename), mp4_file, settings.TIMELAPSE_CONTAINER) with open(last_pic, 'rb') as poster_file: _, poster_file_url = save_file_obj( 'private/{}_poster.jpg'.format(pprint.id), poster_file, settings.TIMELAPSE_CONTAINER) pprint.video_url = mp4_file_url pprint.poster_url = poster_file_url pprint.save() # build tagged timelapse print_pics = filter_pics_by_start_end( list_file_obj('tagged/{}/'.format(pprint.printer.id), settings.PICS_CONTAINER), pprint.started_at, end_time) print_pics.sort() if print_pics: local_pics = download_files(print_pics, to_dir) mp4_filename = '{}_tagged.mp4'.format(pprint.id) output_mp4 = os.path.join(to_dir, mp4_filename) subprocess.run( 'ffmpeg -y -pattern_type glob -i {}/*.jpg -c:v libx264 -vf fps=30 -pix_fmt yuv420p {}' .format(local_pics[0].parent, output_mp4).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 = [ print_pic.replace('tagged/', 'p/').replace('.jpg', '.json') for print_pic in print_pics ] local_jsons = download_files(json_files, to_dir) preidction_json = [] for p_json_file in local_jsons: with open(p_json_file, 'r') as f: try: p_json = json.load(f) except json.decoder.JSONDecodeError: # 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(pprint.id), preidction_json_io, settings.TIMELAPSE_CONTAINER) pprint.tagged_video_url = mp4_file_url pprint.prediction_json_url = json_url pprint.save() shutil.rmtree(to_dir, ignore_errors=True)