def post(self, request):
        printer = request.auth

        pic = request.FILES['pic']
        pic_id = int(timezone.now().timestamp())
        internal_url, external_url = save_file_obj(
            'raw/{}/{}.jpg'.format(printer.id, pic_id), pic,
            settings.PICS_CONTAINER)

        if not printer.is_printing():
            redis.printer_pic_set(printer.id, {'img_url': external_url},
                                  ex=STATUS_TTL_SECONDS)
            return command_response(printer)

        req = requests.get(settings.ML_API_HOST + '/p/',
                           params={'img': internal_url},
                           headers=ml_api_auth_headers(),
                           verify=False)
        req.raise_for_status()
        resp = req.json()

        detections = resp['detections']
        prediction, _ = PrinterPrediction.objects.get_or_create(
            printer=printer)
        update_prediction_with_detections(prediction, detections)
        prediction.save()

        pic.file.seek(
            0)  # Reset file object pointer so that we can load it again
        tagged_img = io.BytesIO()
        detections_to_visualize = [
            d for d in detections if d[1] > VISUALIZATION_THRESH
        ]
        overlay_detections(Image.open(pic),
                           detections_to_visualize).save(tagged_img, "JPEG")
        tagged_img.seek(0)
        _, external_url = save_file_obj(
            'tagged/{}/{}.jpg'.format(printer.id, pic_id), tagged_img,
            settings.PICS_CONTAINER)
        redis.printer_pic_set(printer.id, {'img_url': external_url},
                              ex=STATUS_TTL_SECONDS)

        prediction_json = serializers.serialize("json", [
            prediction,
        ])
        redis.printer_p_json_set(printer.id,
                                 pic_id,
                                 prediction_json,
                                 ex=60 * 60 * 24 * 2)

        if is_failing(prediction,
                      printer.detective_sensitivity,
                      escalating_factor=settings.ESCALATING_FACTOR):
            pause_if_needed(printer)
        elif is_failing(prediction,
                        printer.detective_sensitivity,
                        escalating_factor=1):
            alert_if_needed(printer)

        return command_response(printer)
示例#2
0
    def handle(self, *args, **options):
        timelapse_path = options['timelapse']
        poster_path = options['poster']
        p_json_path = options['p_json']
        creator = options['creator']

        tl_basename = path.basename(timelapse_path)
        post_basename = path.basename(poster_path)

        with open(timelapse_path, 'rb') as tl_file:
            _, tl_url = save_file_obj(tl_basename, tl_file,
                                      settings.TIMELAPSE_CONTAINER)

        with open(poster_path, 'rb') as poster_file:
            _, poster_url = save_file_obj(post_basename, poster_file,
                                          settings.TIMELAPSE_CONTAINER)

        with open(p_json_path, 'r') as f:
            frame_p = json.load(f)

        if len(PublicTimelapse.objects.filter(title=tl_basename)) == 1:
            PublicTimelapse.objects.filter(title=tl_basename).update(
                video_url=tl_url,
                poster_url=poster_url,
                creator_name=creator,
                frame_p=frame_p)
        else:
            PublicTimelapse.objects.create(title=tl_basename,
                                           video_url=tl_url,
                                           poster_url=poster_url,
                                           creator_name=creator,
                                           frame_p=frame_p)
示例#3
0
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)
示例#4
0
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)
示例#5
0
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))
    tl_path = download_files([f'private/{_print.id}.mp4'], tmp_dir, container=settings.TIMELAPSE_CONTAINER)[0]

    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 -i {tl_path} -vf fps={fps} -qscale:v 2 {jpgs_dir}/{print_id}-%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:
            internal_url, _ = save_file_obj(f'raw/uploaded_prints/{jpg_path}', pic, settings.PICS_CONTAINER)
            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 {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)
示例#6
0
def upload_print(request):
    if request.method == 'POST':
        _, file_extension = os.path.splitext(request.FILES['file'].name)
        video_path = f'{str(timezone.now().timestamp())}{file_extension}'
        save_file_obj(f'uploaded/{video_path}', request.FILES['file'], settings.TIMELAPSE_CONTAINER)
        preprocess_timelapse.delay(request.user.id, video_path, request.FILES['file'].name)

        return JsonResponse(dict(status='Ok'))
    else:
        return render(request, 'upload_print.html')
示例#7
0
    def post(self, request):
        printer = request.auth
        printer.refresh_from_db()  # Connection is keep-alive, which means printer object can be stale.

        pic = request.FILES['pic']
        pic = cap_image_size(pic)
        pic_id = str(timezone.now().timestamp())

        if not printer.current_print:     # Some times pics come in when current_print is not set - maybe because printer status is out of sync between plugin and server?
            pic_path = f'{printer.id}/0/{pic_id}.jpg'
        else:
            pic_path = f'{printer.id}/{printer.current_print.id}/{pic_id}.jpg'
        internal_url, external_url = save_file_obj(f'raw/{pic_path}', pic, settings.PICS_CONTAINER, long_term_storage=False)

        if not printer.should_watch() or not printer.actively_printing():
            cache.printer_pic_set(printer.id, {'img_url': external_url}, ex=IMG_URL_TTL_SECONDS)
            send_status_to_web(printer.id)
            return Response({'result': 'ok'})

        req = requests.get(settings.ML_API_HOST + '/p/', params={'img': internal_url}, headers=ml_api_auth_headers(), verify=False)
        req.raise_for_status()
        resp = req.json()

        cache.print_num_predictions_incr(printer.current_print.id)

        detections = resp['detections']
        prediction, _ = PrinterPrediction.objects.get_or_create(printer=printer)
        update_prediction_with_detections(prediction, detections)
        prediction.save()

        if prediction.current_p > settings.THRESHOLD_LOW * 0.2:  # Select predictions high enough for focused feedback
            cache.print_high_prediction_add(printer.current_print.id, prediction.current_p, pic_id)

        pic.file.seek(0)  # Reset file object pointer so that we can load it again
        tagged_img = io.BytesIO()
        detections_to_visualize = [d for d in detections if d[1] > VISUALIZATION_THRESH]
        overlay_detections(Image.open(pic), detections_to_visualize).save(tagged_img, "JPEG")
        tagged_img.seek(0)

        _, external_url = save_file_obj(f'tagged/{pic_path}', tagged_img, settings.PICS_CONTAINER, long_term_storage=False)
        cache.printer_pic_set(printer.id, {'img_url': external_url}, ex=IMG_URL_TTL_SECONDS)

        prediction_json = serializers.serialize("json", [prediction, ])
        p_out = io.BytesIO()
        p_out.write(prediction_json.encode('UTF-8'))
        p_out.seek(0)
        save_file_obj(f'p/{printer.id}/{printer.current_print.id}/{pic_id}.json', p_out, settings.PICS_CONTAINER, long_term_storage=False)

        if is_failing(prediction, printer.detective_sensitivity, escalating_factor=settings.ESCALATING_FACTOR):
            pause_if_needed(printer)
        elif is_failing(prediction, printer.detective_sensitivity, escalating_factor=1):
            alert_if_needed(printer)

        send_status_to_web(printer.id)
        return Response({'result': 'ok'})
    def post(self, request):
        printer = request.auth

        pic = request.FILES['pic']
        pic_id = int(timezone.now().timestamp())
        internal_url, external_url = save_file_obj(
            'raw/{}/{}.jpg'.format(printer.id, pic_id), pic,
            settings.PICS_CONTAINER)

        if not printer.is_printing():
            redis.printer_pic_set(printer.id, {'img_url': external_url},
                                  ex=STATUS_TTL_SECONDS)
            return command_response(printer)

        req = requests.get(settings.ML_API_HOST + '/p/',
                           params={'img': internal_url},
                           headers=ml_api_auth_headers(),
                           verify=False)
        req.raise_for_status()
        resp = req.json()

        detections = resp['detections']
        prediction, _ = PrinterPrediction.objects.get_or_create(
            printer=printer)
        update_prediction_with_detections(prediction, detections)
        prediction.save()

        pic.file.seek(
            0)  # Reset file object pointer so that we can load it again
        tagged_img = io.BytesIO()
        overlay_detections(Image.open(pic),
                           detections).save(tagged_img, "JPEG")
        tagged_img.seek(0)
        _, external_url = save_file_obj(
            'tagged/{}/{}.jpg'.format(printer.id, pic_id), tagged_img,
            settings.PICS_CONTAINER)
        redis.printer_pic_set(printer.id, {'img_url': external_url},
                              ex=STATUS_TTL_SECONDS)

        prediction_json = serializers.serialize("json", [
            prediction,
        ])
        p_out = io.BytesIO()
        p_out.write(prediction_json.encode('UTF-8'))
        p_out.seek(0)
        save_file_obj('p/{}/{}.json'.format(printer.id, pic_id),
                      p_out,
                      settings.PICS_CONTAINER,
                      return_url=False)

        if is_failing(prediction, printer.detective_sensitivity):
            alert_if_needed(printer)

        return command_response(printer)
示例#9
0
def upload_print(request):
    if request.method == 'POST':
        _, file_extension = os.path.splitext(request.FILES['file'].name)
        video_path = f'{str(timezone.now().timestamp())}{file_extension}'
        save_file_obj(f'uploaded/{video_path}', request.FILES['file'], settings.PICS_CONTAINER)
        celery_app.send_task('app_ent.tasks.credit_dh_for_contribution', args=[request.user.id, 1, 'Credit | Upload "{}"'.format(request.FILES['file'].name[:100])])
        preprocess_timelapse.delay(request.user.id, video_path, request.FILES['file'].name)

        return JsonResponse(dict(status='Ok'))
    else:
        return render(request, 'upload_print.html')
示例#10
0
def upload_print(request):
    if request.method == 'POST':
        _, file_extension = os.path.splitext(request.FILES['file'].name)
        video_path = f'{str(timezone.now().timestamp())}{file_extension}'
        save_file_obj(f'uploaded/{video_path}', request.FILES['file'],
                      settings.PICS_CONTAINER)
        user_credit = UserCredit.objects.create(
            user=request.user, reason=UserCredit.TIMELAPSE_UPLOAD, amount=4)
        preprocess_timelapse.delay(request.user.id, video_path,
                                   request.FILES['file'].name, user_credit.id)

        return JsonResponse(dict(status='Ok'))
    else:
        return render(request, 'upload_print.html')
示例#11
0
    def post(self, request):
        printer = request.auth

        pic = request.data['pic']
        internal_url, external_url = save_file_obj('{}/{}.jpg'.format(printer.id, int(time.time())), pic, settings.PICS_CONTAINER)

        if not printer.current_print_filename or not printer.current_print_started_at:
            redis.printer_pic_set(printer.id, {'img_url': external_url, 'p': '0'}, ex=STATUS_TTL_SECONDS)
            return command_response(printer)

        params = {
            'img': internal_url,
            'session_id': "{}|{}".format(printer.id, int(printer.current_print_started_at.timestamp()))
        }

        req = requests.get(settings.ML_API_HOST + '/p', params=params, headers=ml_api_auth_headers(), verify=False)
        req.raise_for_status()
        resp = req.json()
        p = resp['p']
        redis.printer_pic_set(printer.id, {'img_url': external_url, 'p': p}, ex=STATUS_TTL_SECONDS)

        print(resp['detections'])
        print(p)

        send_alert_if_needed(printer, p)
        return command_response(printer)
示例#12
0
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)
示例#13
0
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
示例#14
0
def select_print_shots_for_feedback(_print):

    # Select up to 7 highest predictions that are apart from each other for at least 2 minutes
    def highest_7_predictions(prediction_list):
        selected_timestamps = []

        for pred in prediction_list:
            pred_ts = float(pred[0])
            if len([ts for ts in selected_timestamps if abs(ts - pred_ts) < 120]) > 0:   # timestamp is within 2 minutes from one other selected predictions
                continue

            selected_timestamps += [pred_ts]
            if len(selected_timestamps) >= 7:
                break

        return sorted(selected_timestamps)

    selected_predictions = highest_7_predictions(redis.print_highest_predictions_get(_print.id))

    to_dir = os.path.join(tempfile.gettempdir(), 'ff_' + str(_print.id))
    shutil.rmtree(to_dir, ignore_errors=True)
    os.mkdir(to_dir)

    local_imgs = download_files([f'raw/{_print.printer.id}/{_print.id}/{ts}.jpg' for ts in selected_predictions], to_dir)
    for local_img in local_imgs:
        with open(local_img, 'rb') as local_img_file:
            _, img_url = save_file_obj(f'ff_printshots/raw/{_print.printer.id}/{_print.id}/{local_img.name}', local_img_file, settings.TIMELAPSE_CONTAINER)
            PrintShotFeedback.objects.create(print=_print, image_url=img_url)
示例#15
0
    def post(self, request):
        printer = request.auth
        printer.refresh_from_db() # Connection is keep-alive, which means printer object can be stale.

        if not request.path.startswith('/api/v1'):
            LOGGER.warn(f'Beta plugin connecting from {printer.id}')

        pic = request.FILES['pic']
        pic_id = int(timezone.now().timestamp())
        internal_url, external_url = save_file_obj('raw/{}/{}.jpg'.format(printer.id, pic_id), pic, settings.PICS_CONTAINER)

        if not printer.should_watch() or not printer.actively_printing():
            redis.printer_pic_set(printer.id, {'img_url': external_url}, ex=STATUS_TTL_SECONDS)
            send_status_to_web(printer.id)
            return Response({'result': 'ok'})

        req = requests.get(settings.ML_API_HOST + '/p/', params={'img': internal_url}, headers=ml_api_auth_headers(), verify=False)
        req.raise_for_status()
        resp = req.json()

        detections = resp['detections']
        prediction, _ = PrinterPrediction.objects.get_or_create(printer=printer)
        update_prediction_with_detections(prediction, detections)
        prediction.save()

        pic.file.seek(0)  # Reset file object pointer so that we can load it again
        tagged_img = io.BytesIO()
        detections_to_visualize = [d for d in detections if d[1] > VISUALIZATION_THRESH]
        overlay_detections(Image.open(pic), detections_to_visualize).save(tagged_img, "JPEG")
        tagged_img.seek(0)
        _, external_url = save_file_obj('tagged/{}/{}.jpg'.format(printer.id, pic_id), tagged_img, settings.PICS_CONTAINER)
        redis.printer_pic_set(printer.id, {'img_url': external_url}, ex=STATUS_TTL_SECONDS)

        prediction_json = serializers.serialize("json", [prediction, ])
        redis.printer_p_json_set(printer.id, pic_id, prediction_json, ex=60*60*24*2)

        if is_failing(prediction, printer.detective_sensitivity, escalating_factor=settings.ESCALATING_FACTOR):
            pause_if_needed(printer)
        elif is_failing(prediction, printer.detective_sensitivity, escalating_factor=1):
            alert_if_needed(printer)

        redis.print_num_predictions_incr(printer.current_print.id)
        send_status_to_web(printer.id)
        return Response({'result': 'ok'})
示例#16
0
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)
示例#17
0
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)
示例#18
0
def upload_gcode_file(request):
    if request.method == 'POST':
        _, file_extension = os.path.splitext(request.FILES['file'].name)
        gcode_file = GCodeFile.objects.create(
            user=request.user,
            filename=request.FILES['file'].name,
            safe_filename=re.sub(r'[^\w\.]', '_', request.FILES['file'].name),
            num_bytes=request.FILES['file'].size,
        )
        _, ext_url = save_file_obj(f'{request.user.id}/{gcode_file.id}', request.FILES['file'], settings.GCODE_CONTAINER)
        gcode_file.url = ext_url
        gcode_file.save()

        return JsonResponse(dict(status='Ok'))
    else:
        return render(request, 'upload_print.html')
示例#19
0
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
示例#20
0
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)
示例#21
0
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)
示例#22
0
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)
示例#23
0
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)