endoreg-db 0.8.9.2__py3-none-any.whl → 0.8.9.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/admin.py +10 -5
- endoreg_db/apps.py +4 -7
- endoreg_db/authz/auth.py +1 -0
- endoreg_db/authz/backends.py +1 -1
- endoreg_db/authz/management/commands/list_routes.py +2 -0
- endoreg_db/authz/middleware.py +8 -7
- endoreg_db/authz/permissions.py +21 -10
- endoreg_db/authz/policy.py +14 -19
- endoreg_db/authz/views_auth.py +14 -10
- endoreg_db/codemods/rename_datetime_fields.py +8 -1
- endoreg_db/exceptions.py +5 -2
- endoreg_db/forms/__init__.py +0 -1
- endoreg_db/forms/examination_form.py +4 -3
- endoreg_db/forms/patient_finding_intervention_form.py +30 -8
- endoreg_db/forms/patient_form.py +9 -13
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/settings/__init__.py +4 -1
- endoreg_db/forms/unit.py +2 -1
- endoreg_db/helpers/count_db.py +17 -14
- endoreg_db/helpers/default_objects.py +2 -1
- endoreg_db/helpers/download_segmentation_model.py +4 -3
- endoreg_db/helpers/interact.py +0 -5
- endoreg_db/helpers/test_video_helper.py +33 -25
- endoreg_db/import_files/__init__.py +1 -1
- endoreg_db/import_files/context/__init__.py +1 -1
- endoreg_db/import_files/context/default_sensitive_meta.py +11 -9
- endoreg_db/import_files/context/ensure_center.py +4 -4
- endoreg_db/import_files/context/file_lock.py +3 -3
- endoreg_db/import_files/context/import_context.py +11 -12
- endoreg_db/import_files/context/validate_directories.py +1 -0
- endoreg_db/import_files/file_storage/create_report_file.py +57 -34
- endoreg_db/import_files/file_storage/create_video_file.py +64 -35
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +5 -2
- endoreg_db/import_files/file_storage/state_management.py +89 -122
- endoreg_db/import_files/file_storage/storage.py +5 -1
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +24 -19
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +3 -3
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +18 -18
- endoreg_db/import_files/pseudonymization/k_anonymity.py +8 -9
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +16 -5
- endoreg_db/import_files/report_import_service.py +36 -30
- endoreg_db/import_files/video_import_service.py +27 -23
- endoreg_db/logger_conf.py +56 -40
- endoreg_db/management/__init__.py +1 -1
- endoreg_db/management/commands/__init__.py +1 -1
- endoreg_db/management/commands/check_auth.py +45 -38
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +53 -2
- endoreg_db/management/commands/create_multilabel_model_meta.py +54 -19
- endoreg_db/management/commands/fix_missing_patient_data.py +105 -71
- endoreg_db/management/commands/fix_video_paths.py +75 -54
- endoreg_db/management/commands/import_report.py +1 -3
- endoreg_db/management/commands/list_routes.py +2 -0
- endoreg_db/management/commands/load_ai_model_data.py +8 -2
- endoreg_db/management/commands/load_ai_model_label_data.py +0 -1
- endoreg_db/management/commands/load_center_data.py +3 -3
- endoreg_db/management/commands/load_distribution_data.py +35 -38
- endoreg_db/management/commands/load_endoscope_data.py +0 -3
- endoreg_db/management/commands/load_examination_data.py +20 -4
- endoreg_db/management/commands/load_finding_data.py +18 -3
- endoreg_db/management/commands/load_gender_data.py +17 -24
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +95 -85
- endoreg_db/management/commands/load_information_source.py +0 -3
- endoreg_db/management/commands/load_lab_value_data.py +14 -3
- endoreg_db/management/commands/load_legacy_data.py +303 -0
- endoreg_db/management/commands/load_name_data.py +1 -2
- endoreg_db/management/commands/load_pdf_type_data.py +4 -8
- endoreg_db/management/commands/load_profession_data.py +0 -1
- endoreg_db/management/commands/load_report_reader_flag_data.py +0 -4
- endoreg_db/management/commands/load_requirement_data.py +6 -2
- endoreg_db/management/commands/load_unit_data.py +0 -4
- endoreg_db/management/commands/load_user_groups.py +5 -7
- endoreg_db/management/commands/model_input.py +169 -0
- endoreg_db/management/commands/register_ai_model.py +22 -16
- endoreg_db/management/commands/setup_endoreg_db.py +110 -32
- endoreg_db/management/commands/storage_management.py +14 -8
- endoreg_db/management/commands/summarize_db_content.py +154 -63
- endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
- endoreg_db/management/commands/validate_video_files.py +82 -50
- endoreg_db/management/commands/video_validation.py +4 -6
- endoreg_db/migrations/0001_initial.py +112 -63
- endoreg_db/models/__init__.py +8 -0
- endoreg_db/models/administration/ai/active_model.py +5 -5
- endoreg_db/models/administration/ai/ai_model.py +41 -18
- endoreg_db/models/administration/ai/model_type.py +1 -0
- endoreg_db/models/administration/case/case.py +22 -22
- endoreg_db/models/administration/center/__init__.py +5 -5
- endoreg_db/models/administration/center/center.py +6 -2
- endoreg_db/models/administration/center/center_resource.py +18 -4
- endoreg_db/models/administration/center/center_shift.py +3 -1
- endoreg_db/models/administration/center/center_waste.py +6 -2
- endoreg_db/models/administration/person/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/employee_type.py +3 -1
- endoreg_db/models/administration/person/examiner/__init__.py +1 -1
- endoreg_db/models/administration/person/examiner/examiner.py +10 -2
- endoreg_db/models/administration/person/names/first_name.py +6 -4
- endoreg_db/models/administration/person/names/last_name.py +4 -3
- endoreg_db/models/administration/person/patient/__init__.py +1 -1
- endoreg_db/models/administration/person/patient/patient.py +0 -1
- endoreg_db/models/administration/person/patient/patient_external_id.py +0 -1
- endoreg_db/models/administration/person/person.py +1 -1
- endoreg_db/models/administration/product/__init__.py +7 -6
- endoreg_db/models/administration/product/product.py +6 -2
- endoreg_db/models/administration/product/product_group.py +9 -7
- endoreg_db/models/administration/product/product_material.py +9 -2
- endoreg_db/models/administration/product/reference_product.py +64 -15
- endoreg_db/models/administration/qualification/qualification.py +3 -1
- endoreg_db/models/administration/shift/shift.py +3 -1
- endoreg_db/models/administration/shift/shift_type.py +12 -4
- endoreg_db/models/aidataset/__init__.py +5 -0
- endoreg_db/models/aidataset/aidataset.py +193 -0
- endoreg_db/models/label/__init__.py +1 -1
- endoreg_db/models/label/label.py +10 -2
- endoreg_db/models/label/label_set.py +3 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +6 -2
- endoreg_db/models/label/label_video_segment/label_video_segment.py +148 -44
- endoreg_db/models/media/__init__.py +12 -5
- endoreg_db/models/media/frame/__init__.py +1 -1
- endoreg_db/models/media/frame/frame.py +34 -8
- endoreg_db/models/media/pdf/__init__.py +2 -1
- endoreg_db/models/media/pdf/raw_pdf.py +11 -4
- endoreg_db/models/media/pdf/report_file.py +6 -2
- endoreg_db/models/media/pdf/report_reader/__init__.py +3 -3
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +15 -5
- endoreg_db/models/media/video/create_from_file.py +20 -41
- endoreg_db/models/media/video/pipe_1.py +75 -30
- endoreg_db/models/media/video/pipe_2.py +37 -12
- endoreg_db/models/media/video/video_file.py +36 -24
- endoreg_db/models/media/video/video_file_ai.py +235 -70
- endoreg_db/models/media/video/video_file_anonymize.py +240 -65
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -1
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +30 -9
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +95 -29
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +13 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -1
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +7 -2
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +109 -23
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +111 -27
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +46 -13
- endoreg_db/models/media/video/video_file_io.py +85 -33
- endoreg_db/models/media/video/video_file_meta/__init__.py +6 -6
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +17 -4
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +28 -7
- endoreg_db/models/media/video/video_file_meta/get_fps.py +46 -13
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +81 -20
- endoreg_db/models/media/video/video_file_meta/text_meta.py +61 -20
- endoreg_db/models/media/video/video_file_meta/video_meta.py +40 -12
- endoreg_db/models/media/video/video_file_segments.py +118 -27
- endoreg_db/models/media/video/video_metadata.py +25 -6
- endoreg_db/models/media/video/video_processing.py +54 -15
- endoreg_db/models/medical/__init__.py +3 -13
- endoreg_db/models/medical/contraindication/__init__.py +3 -1
- endoreg_db/models/medical/disease.py +18 -6
- endoreg_db/models/medical/event.py +6 -2
- endoreg_db/models/medical/examination/__init__.py +5 -1
- endoreg_db/models/medical/examination/examination.py +22 -6
- endoreg_db/models/medical/examination/examination_indication.py +23 -7
- endoreg_db/models/medical/examination/examination_time.py +6 -2
- endoreg_db/models/medical/finding/__init__.py +3 -1
- endoreg_db/models/medical/finding/finding.py +37 -12
- endoreg_db/models/medical/finding/finding_classification.py +27 -8
- endoreg_db/models/medical/finding/finding_intervention.py +19 -6
- endoreg_db/models/medical/finding/finding_type.py +3 -1
- endoreg_db/models/medical/hardware/__init__.py +1 -1
- endoreg_db/models/medical/hardware/endoscope.py +14 -2
- endoreg_db/models/medical/laboratory/__init__.py +1 -1
- endoreg_db/models/medical/laboratory/lab_value.py +139 -39
- endoreg_db/models/medical/medication/__init__.py +7 -3
- endoreg_db/models/medical/medication/medication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication_type.py +11 -3
- endoreg_db/models/medical/medication/medication_intake_time.py +3 -1
- endoreg_db/models/medical/medication/medication_schedule.py +3 -1
- endoreg_db/models/medical/patient/__init__.py +2 -10
- endoreg_db/models/medical/patient/medication_examples.py +3 -14
- endoreg_db/models/medical/patient/patient_disease.py +17 -5
- endoreg_db/models/medical/patient/patient_event.py +12 -4
- endoreg_db/models/medical/patient/patient_examination.py +52 -15
- endoreg_db/models/medical/patient/patient_examination_indication.py +15 -4
- endoreg_db/models/medical/patient/patient_finding.py +105 -29
- endoreg_db/models/medical/patient/patient_finding_classification.py +41 -12
- endoreg_db/models/medical/patient/patient_finding_intervention.py +11 -3
- endoreg_db/models/medical/patient/patient_lab_sample.py +6 -2
- endoreg_db/models/medical/patient/patient_lab_value.py +42 -10
- endoreg_db/models/medical/patient/patient_medication.py +25 -7
- endoreg_db/models/medical/patient/patient_medication_schedule.py +34 -10
- endoreg_db/models/metadata/model_meta.py +40 -12
- endoreg_db/models/metadata/model_meta_logic.py +51 -16
- endoreg_db/models/metadata/sensitive_meta.py +65 -28
- endoreg_db/models/metadata/sensitive_meta_logic.py +28 -26
- endoreg_db/models/metadata/video_meta.py +146 -39
- endoreg_db/models/metadata/video_prediction_logic.py +70 -21
- endoreg_db/models/metadata/video_prediction_meta.py +80 -27
- endoreg_db/models/operation_log.py +63 -0
- endoreg_db/models/other/__init__.py +10 -10
- endoreg_db/models/other/distribution/__init__.py +9 -7
- endoreg_db/models/other/distribution/base_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/date_value_distribution.py +19 -5
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/numeric_value_distribution.py +34 -9
- endoreg_db/models/other/emission/__init__.py +1 -1
- endoreg_db/models/other/emission/emission_factor.py +9 -3
- endoreg_db/models/other/information_source.py +15 -5
- endoreg_db/models/other/material.py +3 -1
- endoreg_db/models/other/transport_route.py +3 -1
- endoreg_db/models/other/unit.py +6 -2
- endoreg_db/models/report/report.py +0 -1
- endoreg_db/models/requirement/requirement.py +84 -27
- endoreg_db/models/requirement/requirement_error.py +5 -6
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +1 -1
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +8 -8
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +3 -3
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +24 -8
- endoreg_db/models/requirement/requirement_operator.py +28 -8
- endoreg_db/models/requirement/requirement_set.py +34 -11
- endoreg_db/models/state/__init__.py +1 -0
- endoreg_db/models/state/audit_ledger.py +9 -2
- endoreg_db/models/{media → state}/processing_history/__init__.py +1 -3
- endoreg_db/models/state/processing_history/processing_history.py +136 -0
- endoreg_db/models/state/raw_pdf.py +0 -1
- endoreg_db/models/state/video.py +2 -4
- endoreg_db/models/utils.py +4 -2
- endoreg_db/queries/__init__.py +2 -6
- endoreg_db/queries/annotations/__init__.py +1 -3
- endoreg_db/queries/annotations/legacy.py +37 -26
- endoreg_db/root_urls.py +3 -4
- endoreg_db/schemas/examination_evaluation.py +3 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +249 -163
- endoreg_db/serializers/__init__.py +2 -8
- endoreg_db/serializers/administration/__init__.py +1 -2
- endoreg_db/serializers/administration/ai/__init__.py +0 -1
- endoreg_db/serializers/administration/ai/active_model.py +3 -1
- endoreg_db/serializers/administration/ai/ai_model.py +5 -3
- endoreg_db/serializers/administration/ai/model_type.py +3 -1
- endoreg_db/serializers/administration/center.py +7 -2
- endoreg_db/serializers/administration/gender.py +4 -2
- endoreg_db/serializers/anonymization.py +13 -13
- endoreg_db/serializers/evaluation/examination_evaluation.py +0 -1
- endoreg_db/serializers/examination/__init__.py +1 -1
- endoreg_db/serializers/examination/base.py +12 -13
- endoreg_db/serializers/examination/dropdown.py +6 -7
- endoreg_db/serializers/examination_serializer.py +3 -6
- endoreg_db/serializers/finding/__init__.py +1 -1
- endoreg_db/serializers/finding/finding.py +14 -7
- endoreg_db/serializers/finding_classification/__init__.py +3 -3
- endoreg_db/serializers/finding_classification/choice.py +3 -3
- endoreg_db/serializers/finding_classification/classification.py +2 -4
- endoreg_db/serializers/label_video_segment/__init__.py +5 -3
- endoreg_db/serializers/{label → label_video_segment}/image_classification_annotation.py +5 -5
- endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
- endoreg_db/serializers/{label → label_video_segment/label}/label.py +1 -1
- endoreg_db/serializers/label_video_segment/label_video_segment.py +338 -228
- endoreg_db/serializers/meta/__init__.py +1 -2
- endoreg_db/serializers/meta/sensitive_meta_detail.py +28 -13
- endoreg_db/serializers/meta/sensitive_meta_update.py +51 -46
- endoreg_db/serializers/meta/sensitive_meta_verification.py +19 -16
- endoreg_db/serializers/misc/__init__.py +2 -2
- endoreg_db/serializers/misc/file_overview.py +11 -7
- endoreg_db/serializers/misc/stats.py +10 -8
- endoreg_db/serializers/misc/translatable_field_mix_in.py +6 -6
- endoreg_db/serializers/misc/upload_job.py +32 -29
- endoreg_db/serializers/patient/__init__.py +2 -1
- endoreg_db/serializers/patient/patient.py +32 -15
- endoreg_db/serializers/patient/patient_dropdown.py +11 -3
- endoreg_db/serializers/patient_examination/__init__.py +1 -1
- endoreg_db/serializers/patient_examination/patient_examination.py +67 -40
- endoreg_db/serializers/patient_finding/__init__.py +1 -1
- endoreg_db/serializers/patient_finding/patient_finding.py +2 -1
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +17 -9
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +26 -17
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +7 -5
- endoreg_db/serializers/patient_finding/patient_finding_list.py +10 -11
- endoreg_db/serializers/patient_finding/patient_finding_write.py +36 -27
- endoreg_db/serializers/pdf/__init__.py +1 -3
- endoreg_db/serializers/requirements/requirement_schema.py +1 -6
- endoreg_db/serializers/sensitive_meta_serializer.py +100 -81
- endoreg_db/serializers/video/__init__.py +2 -2
- endoreg_db/serializers/video/{segmentation.py → video_file.py} +66 -47
- endoreg_db/serializers/video/video_file_brief.py +6 -2
- endoreg_db/serializers/video/video_file_detail.py +36 -23
- endoreg_db/serializers/video/video_file_list.py +4 -2
- endoreg_db/serializers/video/video_processing_history.py +54 -50
- endoreg_db/services/__init__.py +1 -1
- endoreg_db/services/anonymization.py +2 -2
- endoreg_db/services/examination_evaluation.py +40 -17
- endoreg_db/services/model_meta_from_hf.py +76 -0
- endoreg_db/services/polling_coordinator.py +101 -70
- endoreg_db/services/pseudonym_service.py +27 -22
- endoreg_db/services/report_import.py +6 -3
- endoreg_db/services/segment_sync.py +75 -59
- endoreg_db/services/video_import.py +6 -7
- endoreg_db/urls/__init__.py +2 -2
- endoreg_db/urls/ai.py +7 -25
- endoreg_db/urls/anonymization.py +61 -15
- endoreg_db/urls/auth.py +4 -4
- endoreg_db/urls/classification.py +4 -9
- endoreg_db/urls/examination.py +27 -18
- endoreg_db/urls/media.py +27 -34
- endoreg_db/urls/patient.py +11 -7
- endoreg_db/urls/requirements.py +3 -1
- endoreg_db/urls/root_urls.py +2 -3
- endoreg_db/urls/stats.py +24 -16
- endoreg_db/urls/upload.py +3 -11
- endoreg_db/utils/__init__.py +14 -15
- endoreg_db/utils/ai/__init__.py +1 -1
- endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
- endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
- endoreg_db/utils/ai/get.py +2 -1
- endoreg_db/utils/ai/inference_dataset.py +14 -15
- endoreg_db/utils/ai/model_training/config.py +117 -0
- endoreg_db/utils/ai/model_training/dataset.py +74 -0
- endoreg_db/utils/ai/model_training/losses.py +68 -0
- endoreg_db/utils/ai/model_training/metrics.py +78 -0
- endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
- endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
- endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +21 -6
- endoreg_db/utils/ai/predict.py +4 -4
- endoreg_db/utils/ai/preprocess.py +19 -11
- endoreg_db/utils/calc_duration_seconds.py +4 -4
- endoreg_db/utils/case_generator/lab_sample_factory.py +3 -4
- endoreg_db/utils/check_video_files.py +74 -47
- endoreg_db/utils/cropping.py +10 -9
- endoreg_db/utils/dataloader.py +11 -3
- endoreg_db/utils/dates.py +3 -4
- endoreg_db/utils/defaults/set_default_center.py +7 -6
- endoreg_db/utils/env.py +6 -2
- endoreg_db/utils/extract_specific_frames.py +24 -9
- endoreg_db/utils/file_operations.py +30 -18
- endoreg_db/utils/fix_video_path_direct.py +57 -41
- endoreg_db/utils/frame_anonymization_utils.py +157 -157
- endoreg_db/utils/hashs.py +3 -18
- endoreg_db/utils/links/requirement_link.py +96 -52
- endoreg_db/utils/ocr.py +30 -25
- endoreg_db/utils/operation_log.py +61 -0
- endoreg_db/utils/parse_and_generate_yaml.py +12 -13
- endoreg_db/utils/paths.py +6 -6
- endoreg_db/utils/permissions.py +40 -24
- endoreg_db/utils/pipelines/process_video_dir.py +50 -26
- endoreg_db/utils/product/sum_emissions.py +5 -3
- endoreg_db/utils/product/sum_weights.py +4 -2
- endoreg_db/utils/pydantic_models/__init__.py +3 -4
- endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +207 -107
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +252 -65
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +27 -10
- endoreg_db/utils/setup_config.py +21 -5
- endoreg_db/utils/storage.py +3 -1
- endoreg_db/utils/translation.py +19 -15
- endoreg_db/utils/uuid.py +1 -0
- endoreg_db/utils/validate_endo_roi.py +12 -4
- endoreg_db/utils/validate_subcategory_dict.py +26 -24
- endoreg_db/utils/validate_video_detailed.py +207 -149
- endoreg_db/utils/video/__init__.py +7 -3
- endoreg_db/utils/video/extract_frames.py +30 -18
- endoreg_db/utils/video/names.py +11 -6
- endoreg_db/utils/video/streaming_processor.py +175 -101
- endoreg_db/utils/video/video_splitter.py +30 -19
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +59 -50
- endoreg_db/views/__init__.py +0 -20
- endoreg_db/views/anonymization/__init__.py +6 -2
- endoreg_db/views/anonymization/media_management.py +2 -6
- endoreg_db/views/anonymization/overview.py +34 -1
- endoreg_db/views/anonymization/validate.py +79 -18
- endoreg_db/views/auth/__init__.py +1 -1
- endoreg_db/views/auth/keycloak.py +16 -14
- endoreg_db/views/examination/__init__.py +12 -15
- endoreg_db/views/examination/examination.py +5 -5
- endoreg_db/views/examination/examination_manifest_cache.py +5 -5
- endoreg_db/views/examination/get_finding_classification_choices.py +8 -5
- endoreg_db/views/examination/get_finding_classifications.py +9 -7
- endoreg_db/views/examination/get_findings.py +8 -10
- endoreg_db/views/examination/get_instruments.py +3 -2
- endoreg_db/views/examination/get_interventions.py +1 -1
- endoreg_db/views/finding/__init__.py +2 -2
- endoreg_db/views/finding/finding.py +58 -54
- endoreg_db/views/finding/get_classifications.py +1 -1
- endoreg_db/views/finding/get_interventions.py +1 -1
- endoreg_db/views/finding_classification/__init__.py +5 -5
- endoreg_db/views/finding_classification/finding_classification.py +5 -6
- endoreg_db/views/finding_classification/get_classification_choices.py +3 -4
- endoreg_db/views/media/__init__.py +13 -13
- endoreg_db/views/media/pdf_media.py +9 -9
- endoreg_db/views/media/sensitive_metadata.py +10 -7
- endoreg_db/views/media/video_media.py +4 -4
- endoreg_db/views/meta/__init__.py +1 -1
- endoreg_db/views/meta/sensitive_meta_list.py +20 -22
- endoreg_db/views/meta/sensitive_meta_verification.py +14 -11
- endoreg_db/views/misc/__init__.py +6 -34
- endoreg_db/views/misc/center.py +2 -1
- endoreg_db/views/misc/csrf.py +2 -1
- endoreg_db/views/misc/gender.py +2 -1
- endoreg_db/views/misc/stats.py +141 -106
- endoreg_db/views/patient/__init__.py +1 -3
- endoreg_db/views/patient/patient.py +141 -99
- endoreg_db/views/patient_examination/__init__.py +5 -5
- endoreg_db/views/patient_examination/patient_examination.py +43 -42
- endoreg_db/views/patient_examination/patient_examination_create.py +10 -15
- endoreg_db/views/patient_examination/patient_examination_detail.py +12 -15
- endoreg_db/views/patient_examination/patient_examination_list.py +21 -17
- endoreg_db/views/patient_examination/video.py +114 -80
- endoreg_db/views/patient_finding/__init__.py +1 -1
- endoreg_db/views/patient_finding/patient_finding.py +17 -10
- endoreg_db/views/patient_finding/patient_finding_optimized.py +127 -95
- endoreg_db/views/patient_finding_classification/__init__.py +1 -1
- endoreg_db/views/patient_finding_classification/pfc_create.py +35 -27
- endoreg_db/views/report/reimport.py +1 -1
- endoreg_db/views/report/report_stream.py +5 -8
- endoreg_db/views/requirement/__init__.py +2 -1
- endoreg_db/views/requirement/evaluate.py +7 -9
- endoreg_db/views/requirement/lookup.py +2 -3
- endoreg_db/views/requirement/lookup_store.py +0 -1
- endoreg_db/views/requirement/requirement_utils.py +2 -4
- endoreg_db/views/stats/__init__.py +4 -4
- endoreg_db/views/stats/stats_views.py +152 -115
- endoreg_db/views/video/__init__.py +18 -27
- endoreg_db/views/{ai → video/ai}/__init__.py +2 -2
- endoreg_db/views/{ai → video/ai}/label.py +20 -16
- endoreg_db/views/video/correction.py +5 -6
- endoreg_db/views/video/reimport.py +134 -99
- endoreg_db/views/video/segments_crud.py +134 -44
- endoreg_db/views/video/video_apply_mask.py +13 -12
- endoreg_db/views/video/video_correction.py +2 -1
- endoreg_db/views/video/video_download_processed.py +15 -15
- endoreg_db/views/video/video_meta_stats.py +7 -6
- endoreg_db/views/video/video_processing_history.py +3 -2
- endoreg_db/views/video/video_remove_frames.py +13 -12
- endoreg_db/views/video/video_stream.py +110 -82
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/METADATA +9 -3
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/RECORD +434 -431
- endoreg_db/management/commands/import_fallback_video.py +0 -203
- endoreg_db/management/commands/import_video.py +0 -422
- endoreg_db/management/commands/import_video_with_classification.py +0 -367
- endoreg_db/models/media/processing_history/processing_history.py +0 -96
- endoreg_db/serializers/label/__init__.py +0 -7
- endoreg_db/serializers/label_video_segment/_lvs_create.py +0 -149
- endoreg_db/serializers/label_video_segment/_lvs_update.py +0 -138
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +0 -149
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +0 -99
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +0 -163
- endoreg_db/services/__old/pdf_import.py +0 -1487
- endoreg_db/services/__old/video_import.py +0 -1306
- endoreg_db/tasks/upload_tasks.py +0 -216
- endoreg_db/tasks/video_ingest.py +0 -161
- endoreg_db/tasks/video_processing_tasks.py +0 -327
- endoreg_db/views/misc/translation.py +0 -182
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.9.2.dist-info → endoreg_db-0.8.9.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -14,14 +14,14 @@ import logging
|
|
|
14
14
|
# Dynamically determine the Django project path
|
|
15
15
|
# previously resolved to "/home/admin/test/lx-annotate/endoreg-db" (endoreg-db project directory)
|
|
16
16
|
project_path = os.environ.get(
|
|
17
|
-
|
|
18
|
-
str(Path(__file__).resolve().parent.parent.parent)
|
|
17
|
+
"ENDOREG_DJANGO_PROJECT_PATH", str(Path(__file__).resolve().parent.parent.parent)
|
|
19
18
|
)
|
|
20
19
|
sys.path.insert(0, project_path)
|
|
21
|
-
os.environ.setdefault(
|
|
20
|
+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dev.dev_settings")
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
import django
|
|
24
|
+
|
|
25
25
|
django.setup()
|
|
26
26
|
|
|
27
27
|
from endoreg_db.models import VideoFile
|
|
@@ -32,8 +32,9 @@ logger = logging.getLogger(__name__)
|
|
|
32
32
|
def check_ffmpeg_available():
|
|
33
33
|
"""Check if FFmpeg is available for video analysis."""
|
|
34
34
|
try:
|
|
35
|
-
result = subprocess.run(
|
|
36
|
-
|
|
35
|
+
result = subprocess.run(
|
|
36
|
+
["ffmpeg", "-version"], capture_output=True, text=True, timeout=10
|
|
37
|
+
)
|
|
37
38
|
return result.returncode == 0
|
|
38
39
|
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
39
40
|
return False
|
|
@@ -44,75 +45,97 @@ def analyze_video_with_ffmpeg(video_path):
|
|
|
44
45
|
Use FFmpeg to analyze video file integrity and get detailed information.
|
|
45
46
|
"""
|
|
46
47
|
analysis_result = {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
"file_readable": False,
|
|
49
|
+
"has_video_stream": False,
|
|
50
|
+
"has_audio_stream": False,
|
|
51
|
+
"duration": None,
|
|
52
|
+
"codec": None,
|
|
53
|
+
"resolution": None,
|
|
54
|
+
"frame_count": None,
|
|
55
|
+
"errors": [],
|
|
56
|
+
"warnings": [],
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
+
|
|
58
59
|
try:
|
|
59
60
|
# First, try to probe the file
|
|
60
61
|
print(f"📊 Analyzing video with FFprobe: {video_path}")
|
|
61
62
|
probe_cmd = [
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
"ffprobe",
|
|
64
|
+
"-v",
|
|
65
|
+
"quiet",
|
|
66
|
+
"-print_format",
|
|
67
|
+
"json",
|
|
68
|
+
"-show_format",
|
|
69
|
+
"-show_streams",
|
|
70
|
+
str(video_path),
|
|
64
71
|
]
|
|
65
|
-
|
|
72
|
+
|
|
66
73
|
result = subprocess.run(probe_cmd, capture_output=True, text=True, timeout=30)
|
|
67
|
-
|
|
74
|
+
|
|
68
75
|
if result.returncode == 0:
|
|
69
|
-
analysis_result[
|
|
76
|
+
analysis_result["file_readable"] = True
|
|
70
77
|
probe_data = json.loads(result.stdout)
|
|
71
|
-
|
|
78
|
+
|
|
72
79
|
# Analyze streams
|
|
73
|
-
if
|
|
74
|
-
for stream in probe_data[
|
|
75
|
-
if stream.get(
|
|
76
|
-
analysis_result[
|
|
77
|
-
analysis_result[
|
|
78
|
-
analysis_result[
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
analysis_result[
|
|
82
|
-
|
|
80
|
+
if "streams" in probe_data:
|
|
81
|
+
for stream in probe_data["streams"]:
|
|
82
|
+
if stream.get("codec_type") == "video":
|
|
83
|
+
analysis_result["has_video_stream"] = True
|
|
84
|
+
analysis_result["codec"] = stream.get("codec_name")
|
|
85
|
+
analysis_result["resolution"] = (
|
|
86
|
+
f"{stream.get('width', '?')}x{stream.get('height', '?')}"
|
|
87
|
+
)
|
|
88
|
+
analysis_result["frame_count"] = stream.get("nb_frames")
|
|
89
|
+
elif stream.get("codec_type") == "audio":
|
|
90
|
+
analysis_result["has_audio_stream"] = True
|
|
91
|
+
|
|
83
92
|
# Get format info
|
|
84
|
-
if
|
|
85
|
-
analysis_result[
|
|
93
|
+
if "format" in probe_data:
|
|
94
|
+
analysis_result["duration"] = float(
|
|
95
|
+
probe_data["format"].get("duration", 0)
|
|
96
|
+
)
|
|
86
97
|
else:
|
|
87
|
-
analysis_result[
|
|
88
|
-
|
|
98
|
+
analysis_result["errors"].append(f"FFprobe failed: {result.stderr}")
|
|
99
|
+
|
|
89
100
|
except subprocess.TimeoutExpired:
|
|
90
|
-
analysis_result[
|
|
101
|
+
analysis_result["errors"].append(
|
|
102
|
+
"FFprobe timed out - file might be severely corrupted"
|
|
103
|
+
)
|
|
91
104
|
except json.JSONDecodeError:
|
|
92
|
-
analysis_result[
|
|
105
|
+
analysis_result["errors"].append("FFprobe returned invalid JSON")
|
|
93
106
|
except Exception as e:
|
|
94
|
-
analysis_result[
|
|
95
|
-
|
|
107
|
+
analysis_result["errors"].append(f"FFprobe analysis failed: {e}")
|
|
108
|
+
|
|
96
109
|
# Try to validate file integrity
|
|
97
110
|
try:
|
|
98
111
|
print("🔍 Testing video integrity...")
|
|
99
112
|
integrity_cmd = [
|
|
100
|
-
|
|
101
|
-
|
|
113
|
+
"ffmpeg",
|
|
114
|
+
"-v",
|
|
115
|
+
"error",
|
|
116
|
+
"-i",
|
|
117
|
+
str(video_path),
|
|
118
|
+
"-f",
|
|
119
|
+
"null",
|
|
120
|
+
"-",
|
|
121
|
+
"-t",
|
|
122
|
+
"5", # Test first 5 seconds
|
|
102
123
|
]
|
|
103
|
-
|
|
104
|
-
result = subprocess.run(
|
|
105
|
-
|
|
124
|
+
|
|
125
|
+
result = subprocess.run(
|
|
126
|
+
integrity_cmd, capture_output=True, text=True, timeout=30
|
|
127
|
+
)
|
|
128
|
+
|
|
106
129
|
if result.returncode == 0:
|
|
107
130
|
print("✅ Video integrity test passed")
|
|
108
131
|
else:
|
|
109
|
-
analysis_result[
|
|
110
|
-
|
|
132
|
+
analysis_result["errors"].append(f"Integrity test failed: {result.stderr}")
|
|
133
|
+
|
|
111
134
|
except subprocess.TimeoutExpired:
|
|
112
|
-
analysis_result[
|
|
135
|
+
analysis_result["errors"].append("Integrity test timed out")
|
|
113
136
|
except Exception as e:
|
|
114
|
-
analysis_result[
|
|
115
|
-
|
|
137
|
+
analysis_result["errors"].append(f"Integrity test failed: {e}")
|
|
138
|
+
|
|
116
139
|
return analysis_result
|
|
117
140
|
|
|
118
141
|
|
|
@@ -121,56 +144,75 @@ def test_video_streaming_compatibility(video_path):
|
|
|
121
144
|
Test if video is compatible with web streaming (H.264 baseline profile recommended).
|
|
122
145
|
"""
|
|
123
146
|
compatibility_result = {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
147
|
+
"web_compatible": False,
|
|
148
|
+
"streaming_friendly": False,
|
|
149
|
+
"needs_conversion": False,
|
|
150
|
+
"recommendations": [],
|
|
128
151
|
}
|
|
129
|
-
|
|
152
|
+
|
|
130
153
|
try:
|
|
131
154
|
# Check codec and profile
|
|
132
155
|
cmd = [
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
156
|
+
"ffprobe",
|
|
157
|
+
"-v",
|
|
158
|
+
"quiet",
|
|
159
|
+
"-select_streams",
|
|
160
|
+
"v:0",
|
|
161
|
+
"-show_entries",
|
|
162
|
+
"stream=codec_name,profile,level,pix_fmt",
|
|
163
|
+
"-of",
|
|
164
|
+
"csv=p=0",
|
|
165
|
+
str(video_path),
|
|
136
166
|
]
|
|
137
|
-
|
|
167
|
+
|
|
138
168
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
|
|
139
|
-
|
|
169
|
+
|
|
140
170
|
if result.returncode == 0:
|
|
141
|
-
codec_info = result.stdout.strip().split(
|
|
171
|
+
codec_info = result.stdout.strip().split(",")
|
|
142
172
|
if len(codec_info) >= 1:
|
|
143
173
|
codec = codec_info[0]
|
|
144
|
-
|
|
145
|
-
if codec ==
|
|
146
|
-
compatibility_result[
|
|
147
|
-
|
|
174
|
+
|
|
175
|
+
if codec == "h264":
|
|
176
|
+
compatibility_result["web_compatible"] = True
|
|
177
|
+
|
|
148
178
|
# Check if moov atom is at the beginning (for streaming)
|
|
149
|
-
moov_cmd = [
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
179
|
+
moov_cmd = [
|
|
180
|
+
"ffprobe",
|
|
181
|
+
"-v",
|
|
182
|
+
"quiet",
|
|
183
|
+
"-show_entries",
|
|
184
|
+
"format",
|
|
185
|
+
"-of",
|
|
186
|
+
"csv=p=0",
|
|
187
|
+
str(video_path),
|
|
188
|
+
]
|
|
189
|
+
moov_result = subprocess.run(
|
|
190
|
+
moov_cmd, capture_output=True, text=True, timeout=10
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
if "mov,mp4" in moov_result.stdout:
|
|
194
|
+
compatibility_result["streaming_friendly"] = True
|
|
155
195
|
else:
|
|
156
|
-
compatibility_result[
|
|
196
|
+
compatibility_result["recommendations"].append(
|
|
157
197
|
"Consider re-encoding with 'faststart' flag for better streaming"
|
|
158
198
|
)
|
|
159
|
-
|
|
160
|
-
elif codec in [
|
|
161
|
-
compatibility_result[
|
|
199
|
+
|
|
200
|
+
elif codec in ["hevc", "h265"]:
|
|
201
|
+
compatibility_result["recommendations"].append(
|
|
162
202
|
"HEVC/H.265 codec may not be supported in all browsers"
|
|
163
203
|
)
|
|
164
|
-
compatibility_result[
|
|
204
|
+
compatibility_result["needs_conversion"] = True
|
|
165
205
|
else:
|
|
166
|
-
compatibility_result[
|
|
206
|
+
compatibility_result["recommendations"].append(
|
|
167
207
|
f"Codec '{codec}' may not be web-compatible. Consider H.264"
|
|
168
208
|
)
|
|
169
|
-
compatibility_result[
|
|
170
|
-
|
|
209
|
+
compatibility_result["needs_conversion"] = True
|
|
210
|
+
|
|
171
211
|
except Exception as e:
|
|
172
|
-
compatibility_result[
|
|
173
|
-
|
|
212
|
+
compatibility_result["recommendations"].append(
|
|
213
|
+
f"Could not analyze compatibility: {e}"
|
|
214
|
+
)
|
|
215
|
+
|
|
174
216
|
return compatibility_result
|
|
175
217
|
|
|
176
218
|
|
|
@@ -179,64 +221,74 @@ def test_django_video_access(video_id):
|
|
|
179
221
|
Test accessing the video through Django ORM and methods.
|
|
180
222
|
"""
|
|
181
223
|
access_result = {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
224
|
+
"orm_accessible": False,
|
|
225
|
+
"has_raw_file": False,
|
|
226
|
+
"has_processed_file": False,
|
|
227
|
+
"active_file_path": None,
|
|
228
|
+
"file_size": 0,
|
|
229
|
+
"errors": [],
|
|
188
230
|
}
|
|
189
|
-
|
|
231
|
+
|
|
190
232
|
try:
|
|
191
233
|
video = VideoFile.objects.get(pk=video_id)
|
|
192
|
-
access_result[
|
|
193
|
-
|
|
234
|
+
access_result["orm_accessible"] = True
|
|
235
|
+
|
|
194
236
|
# Check raw file
|
|
195
|
-
if hasattr(video,
|
|
237
|
+
if hasattr(video, "raw_file") and video.raw_file:
|
|
196
238
|
try:
|
|
197
239
|
raw_path = video.raw_file.path
|
|
198
240
|
if Path(raw_path).exists():
|
|
199
|
-
access_result[
|
|
200
|
-
access_result[
|
|
201
|
-
access_result[
|
|
241
|
+
access_result["has_raw_file"] = True
|
|
242
|
+
access_result["active_file_path"] = raw_path
|
|
243
|
+
access_result["file_size"] = Path(raw_path).stat().st_size
|
|
202
244
|
except Exception as e:
|
|
203
|
-
access_result[
|
|
204
|
-
|
|
245
|
+
access_result["errors"].append(f"Raw file access error: {e}")
|
|
246
|
+
|
|
205
247
|
# Check processed file
|
|
206
|
-
if hasattr(video,
|
|
248
|
+
if hasattr(video, "processed_file") and video.processed_file:
|
|
207
249
|
try:
|
|
208
250
|
processed_path = video.processed_file.path
|
|
209
251
|
if Path(processed_path).exists():
|
|
210
|
-
access_result[
|
|
211
|
-
if not access_result[
|
|
212
|
-
access_result[
|
|
213
|
-
access_result[
|
|
252
|
+
access_result["has_processed_file"] = True
|
|
253
|
+
if not access_result["active_file_path"]:
|
|
254
|
+
access_result["active_file_path"] = processed_path
|
|
255
|
+
access_result["file_size"] = Path(processed_path).stat().st_size
|
|
214
256
|
except Exception as e:
|
|
215
|
-
access_result[
|
|
216
|
-
|
|
257
|
+
access_result["errors"].append(f"Processed file access error: {e}")
|
|
258
|
+
|
|
217
259
|
# Test video streaming methods
|
|
218
260
|
try:
|
|
219
|
-
if hasattr(video,
|
|
261
|
+
if hasattr(video, "get_active_file_path"):
|
|
220
262
|
active_path = video.get_active_file_path()
|
|
221
263
|
if active_path and Path(active_path).exists():
|
|
222
|
-
access_result[
|
|
223
|
-
access_result[
|
|
264
|
+
access_result["active_file_path"] = str(active_path)
|
|
265
|
+
access_result["file_size"] = Path(active_path).stat().st_size
|
|
224
266
|
except Exception as e:
|
|
225
|
-
access_result[
|
|
226
|
-
|
|
267
|
+
access_result["errors"].append(f"Active file path method error: {e}")
|
|
268
|
+
|
|
227
269
|
except VideoFile.DoesNotExist:
|
|
228
|
-
access_result[
|
|
270
|
+
access_result["errors"].append(
|
|
271
|
+
f"Video with ID {video_id} not found in database"
|
|
272
|
+
)
|
|
229
273
|
except Exception as e:
|
|
230
|
-
access_result[
|
|
231
|
-
|
|
274
|
+
access_result["errors"].append(f"Django access error: {e}")
|
|
275
|
+
|
|
232
276
|
return access_result
|
|
233
277
|
|
|
234
278
|
|
|
235
279
|
def main():
|
|
236
280
|
import argparse
|
|
237
281
|
|
|
238
|
-
parser = argparse.ArgumentParser(
|
|
239
|
-
|
|
282
|
+
parser = argparse.ArgumentParser(
|
|
283
|
+
description="Comprehensive video file validation script for debugging streaming issues."
|
|
284
|
+
)
|
|
285
|
+
parser.add_argument(
|
|
286
|
+
"video_id",
|
|
287
|
+
nargs="?",
|
|
288
|
+
type=int,
|
|
289
|
+
default=5,
|
|
290
|
+
help="ID of the video to validate (default: 5)",
|
|
291
|
+
)
|
|
240
292
|
args = parser.parse_args()
|
|
241
293
|
|
|
242
294
|
video_id = args.video_id
|
|
@@ -245,38 +297,38 @@ def main():
|
|
|
245
297
|
print("=" * 50)
|
|
246
298
|
print(f"Testing video ID: {video_id}")
|
|
247
299
|
print()
|
|
248
|
-
|
|
300
|
+
|
|
249
301
|
# Test Django access
|
|
250
302
|
print("1️⃣ Testing Django ORM Access...")
|
|
251
303
|
django_result = test_django_video_access(video_id)
|
|
252
|
-
|
|
253
|
-
if django_result[
|
|
304
|
+
|
|
305
|
+
if django_result["orm_accessible"]:
|
|
254
306
|
print("✅ Video found in database")
|
|
255
307
|
print(f"📁 Active file path: {django_result['active_file_path']}")
|
|
256
|
-
print(f"📏 File size: {django_result['file_size'] / (1024*1024):.1f} MB")
|
|
257
|
-
|
|
258
|
-
if django_result[
|
|
259
|
-
for error in django_result[
|
|
308
|
+
print(f"📏 File size: {django_result['file_size'] / (1024 * 1024):.1f} MB")
|
|
309
|
+
|
|
310
|
+
if django_result["errors"]:
|
|
311
|
+
for error in django_result["errors"]:
|
|
260
312
|
print(f"⚠️ {error}")
|
|
261
313
|
else:
|
|
262
314
|
print("❌ Video not accessible through Django")
|
|
263
|
-
for error in django_result[
|
|
315
|
+
for error in django_result["errors"]:
|
|
264
316
|
print(f"❌ {error}")
|
|
265
317
|
return
|
|
266
|
-
|
|
318
|
+
|
|
267
319
|
# Get video file path for further testing
|
|
268
|
-
video_path = django_result[
|
|
320
|
+
video_path = django_result["active_file_path"]
|
|
269
321
|
if not video_path or not Path(video_path).exists():
|
|
270
322
|
print("❌ No valid video file path found")
|
|
271
323
|
return
|
|
272
|
-
|
|
324
|
+
|
|
273
325
|
print("\n2️⃣ Testing File System Access...")
|
|
274
326
|
file_path = Path(video_path)
|
|
275
327
|
print(f"📁 Path: {file_path}")
|
|
276
328
|
print(f"✅ File exists: {file_path.exists()}")
|
|
277
|
-
print(f"📏 Size: {file_path.stat().st_size / (1024*1024):.1f} MB")
|
|
329
|
+
print(f"📏 Size: {file_path.stat().st_size / (1024 * 1024):.1f} MB")
|
|
278
330
|
print(f"🔑 Readable: {os.access(file_path, os.R_OK)}")
|
|
279
|
-
|
|
331
|
+
|
|
280
332
|
# Check FFmpeg availability
|
|
281
333
|
print("\n3️⃣ Checking FFmpeg Availability...")
|
|
282
334
|
if not check_ffmpeg_available():
|
|
@@ -285,73 +337,79 @@ def main():
|
|
|
285
337
|
return
|
|
286
338
|
else:
|
|
287
339
|
print("✅ FFmpeg is available")
|
|
288
|
-
|
|
340
|
+
|
|
289
341
|
# Analyze video with FFmpeg
|
|
290
342
|
print("\n4️⃣ Video Analysis with FFmpeg...")
|
|
291
343
|
analysis = analyze_video_with_ffmpeg(video_path)
|
|
292
|
-
|
|
293
|
-
if analysis[
|
|
344
|
+
|
|
345
|
+
if analysis["file_readable"]:
|
|
294
346
|
print("✅ File is readable by FFmpeg")
|
|
295
347
|
print(f"🎥 Has video stream: {analysis['has_video_stream']}")
|
|
296
348
|
print(f"🔊 Has audio stream: {analysis['has_audio_stream']}")
|
|
297
|
-
print(
|
|
349
|
+
print(
|
|
350
|
+
f"⏱️ Duration: {analysis['duration']:.2f}s"
|
|
351
|
+
if analysis["duration"]
|
|
352
|
+
else "⏱️ Duration: Unknown"
|
|
353
|
+
)
|
|
298
354
|
print(f"🎬 Codec: {analysis['codec'] or 'Unknown'}")
|
|
299
355
|
print(f"📐 Resolution: {analysis['resolution'] or 'Unknown'}")
|
|
300
356
|
print(f"🖼️ Frame count: {analysis['frame_count'] or 'Unknown'}")
|
|
301
357
|
else:
|
|
302
358
|
print("❌ File is NOT readable by FFmpeg")
|
|
303
|
-
|
|
304
|
-
if analysis[
|
|
359
|
+
|
|
360
|
+
if analysis["errors"]:
|
|
305
361
|
print("\n❌ Errors found:")
|
|
306
|
-
for error in analysis[
|
|
362
|
+
for error in analysis["errors"]:
|
|
307
363
|
print(f" • {error}")
|
|
308
|
-
|
|
309
|
-
if analysis[
|
|
364
|
+
|
|
365
|
+
if analysis["warnings"]:
|
|
310
366
|
print("\n⚠️ Warnings:")
|
|
311
|
-
for warning in analysis[
|
|
367
|
+
for warning in analysis["warnings"]:
|
|
312
368
|
print(f" • {warning}")
|
|
313
|
-
|
|
369
|
+
|
|
314
370
|
# Test streaming compatibility
|
|
315
371
|
print("\n5️⃣ Testing Web Streaming Compatibility...")
|
|
316
372
|
compatibility = test_video_streaming_compatibility(video_path)
|
|
317
|
-
|
|
373
|
+
|
|
318
374
|
print(f"🌐 Web compatible: {compatibility['web_compatible']}")
|
|
319
375
|
print(f"📡 Streaming friendly: {compatibility['streaming_friendly']}")
|
|
320
376
|
print(f"🔄 Needs conversion: {compatibility['needs_conversion']}")
|
|
321
|
-
|
|
322
|
-
if compatibility[
|
|
377
|
+
|
|
378
|
+
if compatibility["recommendations"]:
|
|
323
379
|
print("\n💡 Recommendations:")
|
|
324
|
-
for rec in compatibility[
|
|
380
|
+
for rec in compatibility["recommendations"]:
|
|
325
381
|
print(f" • {rec}")
|
|
326
|
-
|
|
382
|
+
|
|
327
383
|
# Final diagnosis
|
|
328
384
|
print("\n6️⃣ DIAGNOSIS")
|
|
329
385
|
print("=" * 30)
|
|
330
|
-
|
|
331
|
-
if not analysis[
|
|
386
|
+
|
|
387
|
+
if not analysis["file_readable"]:
|
|
332
388
|
print("🔴 CRITICAL: Video file is corrupted or unreadable")
|
|
333
389
|
print("📋 Action: Replace or re-encode the video file")
|
|
334
|
-
elif not analysis[
|
|
390
|
+
elif not analysis["has_video_stream"]:
|
|
335
391
|
print("🔴 CRITICAL: No video stream found")
|
|
336
392
|
print("📋 Action: Check if file is actually a video")
|
|
337
|
-
elif not compatibility[
|
|
393
|
+
elif not compatibility["web_compatible"]:
|
|
338
394
|
print("🟡 WARNING: Video may not be web-compatible")
|
|
339
395
|
print("📋 Action: Consider re-encoding to H.264")
|
|
340
|
-
elif not compatibility[
|
|
396
|
+
elif not compatibility["streaming_friendly"]:
|
|
341
397
|
print("🟡 WARNING: Video not optimized for streaming")
|
|
342
398
|
print("📋 Action: Re-encode with faststart flag")
|
|
343
399
|
else:
|
|
344
400
|
print("🟢 GOOD: Video appears to be valid and web-compatible")
|
|
345
401
|
print("📋 Issue likely in Django streaming view or network connection")
|
|
346
|
-
|
|
402
|
+
|
|
347
403
|
print("\n🔧 Suggested fixes for streaming issues:")
|
|
348
404
|
print("1. Check Django VideoStreamView implementation")
|
|
349
405
|
print("2. Verify file permissions (readable by web server)")
|
|
350
406
|
print("3. Test with a different video file")
|
|
351
407
|
print("4. Check browser developer tools for specific errors")
|
|
352
408
|
print("5. Consider re-encoding the video:")
|
|
353
|
-
print(
|
|
409
|
+
print(
|
|
410
|
+
f" ffmpeg -i '{video_path}' -c:v libx264 -profile:v baseline -level 3.0 -movflags faststart output.mp4"
|
|
411
|
+
)
|
|
354
412
|
|
|
355
413
|
|
|
356
414
|
if __name__ == "__main__":
|
|
357
|
-
main()
|
|
415
|
+
main()
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
from .video_splitter import split_video
|
|
2
|
-
from .names import
|
|
2
|
+
from .names import (
|
|
3
|
+
get_video_key,
|
|
4
|
+
identify_video_key,
|
|
5
|
+
get_video_key_regex_by_examination_alias,
|
|
6
|
+
)
|
|
3
7
|
|
|
4
8
|
# Add necessary functions from ffmpeg_wrapper
|
|
5
9
|
from .ffmpeg_wrapper import (
|
|
@@ -7,7 +11,7 @@ from .ffmpeg_wrapper import (
|
|
|
7
11
|
assemble_video_from_frames,
|
|
8
12
|
transcode_video,
|
|
9
13
|
transcode_videofile_if_required,
|
|
10
|
-
extract_frames as ffmpeg_extract_frames
|
|
14
|
+
extract_frames as ffmpeg_extract_frames, # Alias to avoid potential name clash if 'extract_frames' was used elsewhere directly from __init__
|
|
11
15
|
)
|
|
12
16
|
|
|
13
17
|
|
|
@@ -22,5 +26,5 @@ __all__ = [
|
|
|
22
26
|
"assemble_video_from_frames",
|
|
23
27
|
"transcode_video",
|
|
24
28
|
"transcode_videofile_if_required",
|
|
25
|
-
"ffmpeg_extract_frames",
|
|
29
|
+
"ffmpeg_extract_frames", # Use the alias if needed
|
|
26
30
|
]
|