def preprocess_timelapse(self, user_id, video_path, filename): tmp_file_path = os.path.join(tempfile.gettempdir(), video_path) converted_mp4_path = tmp_file_path + '.mp4' Path(tmp_file_path).parent.mkdir(parents=True, exist_ok=True) with open(tmp_file_path, 'wb') as file_obj: retrieve_to_file_obj(f'uploaded/{video_path}', file_obj, settings.PICS_CONTAINER, long_term_storage=False) subprocess.run( f'ffmpeg -y -i {tmp_file_path} -c:v libx264 -pix_fmt yuv420p {converted_mp4_path}' .split(), check=True) _print = Print.objects.create(user_id=user_id, filename=filename, uploaded_at=timezone.now()) with open(converted_mp4_path, 'rb') as mp4_file: _, video_url = save_file_obj(f'private/{_print.id}.mp4', mp4_file, settings.TIMELAPSE_CONTAINER) _print.video_url = video_url _print.save() detect_timelapse.delay(_print.id) os.remove(tmp_file_path) os.remove(converted_mp4_path)
def save_print_snapshot(_print, input_path, unrotated_jpg_path=None, rotated_jpg_path=None, to_container=settings.TIMELAPSE_CONTAINER, to_long_term_storage=True): if not input_path: return (None, None) to_dir = tempfile.mkdtemp() shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) unrotated_jpg = os.path.join(to_dir, 'unrotated.jpg') with open(unrotated_jpg, 'wb') as file_obj: retrieve_to_file_obj(input_path, file_obj, settings.PICS_CONTAINER, long_term_storage=False) (unrotated_jpg_url, rotated_jpg_url) = (None, None) if unrotated_jpg_path: with open(unrotated_jpg, 'rb') as file_obj: _, unrotated_jpg_url = save_file_obj(unrotated_jpg_path, file_obj, to_container, long_term_storage=to_long_term_storage) if rotated_jpg_path: 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 file_obj: _, rotated_jpg_url = save_file_obj(rotated_jpg_path, file_obj, to_container, long_term_storage=to_long_term_storage) shutil.rmtree(to_dir, ignore_errors=True) return (unrotated_jpg_url, rotated_jpg_url)
def save_print_snapshot(printer, input_path, dest_jpg_path, rotated=False, to_container=settings.PICS_CONTAINER, to_long_term_storage=True): if not input_path: return None img_bytes = io.BytesIO() retrieve_to_file_obj(input_path, img_bytes, settings.PICS_CONTAINER, long_term_storage=False) img_bytes.seek(0) tmp_img = Image.open(img_bytes) if rotated: if printer.settings['webcam_flipH']: tmp_img = tmp_img.transpose(Image.FLIP_LEFT_RIGHT) if printer.settings['webcam_flipV']: tmp_img = tmp_img.transpose(Image.FLIP_TOP_BOTTOM) if printer.settings['webcam_rotate90']: tmp_img = tmp_img.transpose(Image.ROTATE_90) img_bytes = io.BytesIO() tmp_img.save(img_bytes, "JPEG") img_bytes.seek(0) _, dest_jpg_url = save_file_obj(dest_jpg_path, img_bytes, to_container, long_term_storage=to_long_term_storage) return dest_jpg_url
def download_files(filenames, to_dir, container=settings.PICS_CONTAINER): output_files = [] for filename in filenames: output_path = Path(os.path.join(to_dir, filename)) output_path.parent.mkdir(parents=True, exist_ok=True) with open(output_path, 'wb') as file_obj: retrieve_to_file_obj(filename, file_obj, container) output_files += [output_path] return output_files
def save_print_snapshot(_print, rotated_jpg_path, rotated_jpg_container, rotated_jpg_long_term): 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 (None, None) 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, 'unrotated.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 file_obj: _, unrotated_jpg_url = save_file_obj( f'raw/{_print.printer.id}/unrotated.jpg', file_obj, settings.PICS_CONTAINER, long_term_storage=False) 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 file_obj: _, rotated_jpg_url = save_file_obj( rotated_jpg_path, file_obj, rotated_jpg_container, long_term_storage=rotated_jpg_long_term) shutil.rmtree(to_dir, ignore_errors=True) return (unrotated_jpg_url, rotated_jpg_url)
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 save_print_snapshot(_print, input_path, dest_jpg_path, rotated=False, to_container=settings.PICS_CONTAINER, to_long_term_storage=True): if not input_path: return None to_dir = tempfile.mkdtemp() shutil.rmtree(to_dir, ignore_errors=True) os.mkdir(to_dir) temp_jpg = os.path.join(to_dir, 'unrotated.jpg') with open(temp_jpg, 'wb') as file_obj: retrieve_to_file_obj(input_path, file_obj, settings.PICS_CONTAINER, long_term_storage=False) if not rotated: dest_jpg = temp_jpg else: ffmpeg_extra_options = orientation_to_ffmpeg_options( _print.printer.settings) dest_jpg = os.path.join(to_dir, 'rotated.jpg') cmd = f'ffmpeg -y -i {temp_jpg} {ffmpeg_extra_options} {dest_jpg}' subprocess.run(cmd.split(), check=True) with open(dest_jpg, 'rb') as file_obj: _, dest_jpg_url = save_file_obj(dest_jpg_path, file_obj, to_container, long_term_storage=to_long_term_storage) shutil.rmtree(to_dir, ignore_errors=True) return dest_jpg_url
def detect_timelapse(self, print_id): MAX_FRAME_NUM = 750 _print = Print.objects.get(pk=print_id) tmp_dir = os.path.join(tempfile.gettempdir(), str(_print.id)) mp4_filepath = f'private/{_print.id}.mp4' tl_path = os.path.join(tmp_dir, mp4_filepath) Path(tl_path).parent.mkdir(parents=True, exist_ok=True) with open(tl_path, 'wb') as file_obj: retrieve_to_file_obj(mp4_filepath, file_obj, settings.TIMELAPSE_CONTAINER) jpgs_dir = os.path.join(tmp_dir, 'jpgs') shutil.rmtree(jpgs_dir, ignore_errors=True) os.makedirs(jpgs_dir) tagged_jpgs_dir = os.path.join(tmp_dir, 'tagged_jpgs') shutil.rmtree(tagged_jpgs_dir, ignore_errors=True) os.makedirs(tagged_jpgs_dir) ffprobe_cmd = subprocess.run( f'ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 {tl_path}' .split(), stdout=subprocess.PIPE) frame_num = int(ffprobe_cmd.stdout.strip()) fps = 30 * MAX_FRAME_NUM / frame_num if frame_num > MAX_FRAME_NUM else 30 subprocess.run( f'ffmpeg -y -i {tl_path} -vf fps={fps} -qscale:v 2 {jpgs_dir}/%5d.jpg'. split()) predictions = [] last_prediction = PrinterPrediction() jpg_filenames = sorted(os.listdir(jpgs_dir)) for jpg_path in jpg_filenames: jpg_abs_path = os.path.join(jpgs_dir, jpg_path) with open(jpg_abs_path, 'rb') as pic: pic_path = f'{_print.user.id}/{_print.id}/{jpg_path}' internal_url, _ = save_file_obj(f'uploaded/{pic_path}', pic, settings.PICS_CONTAINER, long_term_storage=False) req = requests.get(settings.ML_API_HOST + '/p/', params={'img': internal_url}, headers=ml_api_auth_headers(), verify=False) req.raise_for_status() detections = req.json()['detections'] update_prediction_with_detections(last_prediction, detections) predictions.append(last_prediction) if is_failing(last_prediction, 1, escalating_factor=1): _print.alerted_at = timezone.now() last_prediction = copy.deepcopy(last_prediction) detections_to_visualize = [ d for d in detections if d[1] > VISUALIZATION_THRESH ] overlay_detections(Image.open(jpg_abs_path), detections_to_visualize).save( os.path.join(tagged_jpgs_dir, jpg_path), "JPEG") predictions_json = serializers.serialize("json", predictions) _, json_url = save_file_obj(f'private/{_print.id}_p.json', io.BytesIO(str.encode(predictions_json)), settings.TIMELAPSE_CONTAINER) mp4_filename = f'{_print.id}_tagged.mp4' output_mp4 = os.path.join(tmp_dir, mp4_filename) subprocess.run( f'ffmpeg -y -r 30 -pattern_type glob -i {tagged_jpgs_dir}/*.jpg -c:v libx264 -pix_fmt yuv420p -vf pad=ceil(iw/2)*2:ceil(ih/2)*2 {output_mp4}' .split(), check=True) with open(output_mp4, 'rb') as mp4_file: _, mp4_file_url = save_file_obj(f'private/{mp4_filename}', mp4_file, settings.TIMELAPSE_CONTAINER) with open(os.path.join(jpgs_dir, jpg_filenames[-1]), 'rb') as poster_file: _, poster_file_url = save_file_obj(f'private/{_print.id}_poster.jpg', poster_file, settings.TIMELAPSE_CONTAINER) _print.tagged_video_url = mp4_file_url _print.prediction_json_url = json_url _print.poster_url = poster_file_url _print.save() shutil.rmtree(tmp_dir, ignore_errors=True) send_timelapse_detection_done_email(_print) delete_dir(f'uploaded/{_print.user.id}/{_print.id}/', settings.PICS_CONTAINER, long_term_storage=False)