Commit Graph

61 Commits

Author SHA1 Message Date
JSLMPR 1c3db181a3 Add edit sound effect cues 2026-07-10 18:47:18 +02:00
JSLMPR e2037a7629 Add basic edit transitions 2026-07-10 16:19:05 +02:00
JSLMPR c3c6c7a790 Add edit render manifest 2026-07-10 16:16:13 +02:00
JSLMPR a3ca4826f5 Add edit audio mixing 2026-07-10 16:15:09 +02:00
JSLMPR 46a4982ef9 Add concat edit timeline rendering 2026-07-10 16:13:59 +02:00
JSLMPR 21e5cef45d Add normalized edit segment rendering 2026-07-10 16:08:08 +02:00
JSLMPR 2b4c5992a6 Add edit plan API 2026-07-10 16:00:49 +02:00
JSLMPR 4979e4da25 Add strict edit plan validation 2026-07-10 15:55:59 +02:00
JSLMPR a3317cfb43 Add edit plan inbox pickup 2026-07-10 15:52:35 +02:00
JSLMPR 9c0a2e88e3 Add local director project scheduler 2026-07-10 15:43:04 +02:00
JSLMPR f8d0bc874e Add local AI director prompt generation 2026-07-10 15:38:16 +02:00
JSLMPR 8a1dd0ac3a Add cinematic storyboard prompt generation 2026-07-10 15:35:15 +02:00
JSLMPR 0ccfd99147 Add cinematic analysis writer 2026-07-10 15:30:37 +02:00
JSLMPR a5b8ed10a3 Add cinematic proxy generation 2026-07-10 15:24:28 +02:00
JSLMPR d7712bbc01 Add cinematic contact sheet generation 2026-07-10 15:17:45 +02:00
JSLMPR b736df6cad Add cinematic thumbnail extraction 2026-07-10 15:15:00 +02:00
JSLMPR 67f0a0d423 Add cinematic ffprobe clip inspection 2026-07-10 15:06:59 +02:00
JSLMPR 28fbfadd6e Add cinematic edit clip discovery 2026-07-10 14:57:00 +02:00
JSLMPR 8d8180dc61 Add cinematic edit project API 2026-07-10 14:53:02 +02:00
JSLMPR 0d4752897d Add cinematic edit domain model 2026-07-10 14:48:42 +02:00
JSLMPR fdd8309311 Add cinematic edit project store 2026-07-10 14:41:52 +02:00
JSLMPR 754bf35cbe Add cinematic editing configuration 2026-07-10 14:30:18 +02:00
JSLMPR 7fd92a72df Configure folder scheduler in YAML 2026-07-10 12:24:16 +02:00
JSLMPR b61ab0604a Improve folder scheduler diagnostics 2026-07-10 10:14:24 +02:00
JSLMPR c08acb5f18 Complete folder scheduler verification 2026-07-10 09:03:31 +02:00
JSLMPR 8e67566f0d Document local folder scheduler profile 2026-07-10 08:58:25 +02:00
JSLMPR 90cadbe097 Add real FFmpeg scheduler integration test 2026-07-10 08:56:51 +02:00
JSLMPR f96d0689e1 Complete scheduler state transition tests 2026-07-10 08:45:58 +02:00
JSLMPR 4b0be45be0 Handle scheduled clipping failures 2026-07-10 08:44:54 +02:00
JSLMPR 020edf9821 Archive successfully clipped sources 2026-07-10 08:41:34 +02:00
JSLMPR aaacd7f592 Generate exact FFmpeg folder clips 2026-07-10 08:35:39 +02:00
JSLMPR cf28898ecf Reject invalid scheduled inputs 2026-07-10 08:29:01 +02:00
JSLMPR 146c37b091 Add ffprobe video validation 2026-07-10 02:06:24 +02:00
JSLMPR 45092e23b0 Implement scheduler input claiming 2026-07-10 01:38:33 +02:00
JSLMPR 702d768e33 • Added missing tests and a 100% coverage gate for the new folder scheduler package.
Changes:

  - Added JaCoCo to pom.xml with a 100% instruction, line, and branch coverage rule scoped to org.example.videoclips.folder.
  - Added src/test/java/org/example/videoclips/folder/FolderSchedulerDirectoryInitializerTest.java.
  - Added src/test/java/org/example/videoclips/folder/FolderVideoScanSchedulerTest.java.
  - Adjusted the scanner comparator in src/main/java/org/example/videoclips/folder/FolderVideoScanScheduler.java to keep deterministic ordering without an uncovered comparator branch.

  Verification: mvn -q verify passed. The generated JaCoCo report shows org.example.videoclips.folder at 100% instruction, line, and branch coverage.

  Scope note: this enforces 100% coverage for the new scheduler package, not the whole existing service. Project-wide 100% would be a much larger pass across pre-existing classes. The next
  scheduler milestone is repeat-prevention by moving selected inputs to the working folder before processing.
2026-07-10 01:02:08 +02:00
JSLMPR 97cc4ff4e4 • Implemented the next Input Folder Scheduler Plan milestone: startup directory initialization.
Added src/main/java/org/example/videoclips/folder/FolderSchedulerDirectoryInitializer.java, which creates the configured input, output, working, processed, and rejected directories when video-clipping.folder-
  scheduler.enabled=true. It stays inactive by default, so normal startup will not fail on machines where /input and /output cannot be created.

  Updated docs/input-folder-scheduler-plan.md to mark milestone 3 complete.
2026-07-10 00:52:40 +02:00
JSLMPR 1b9246bafe I added a reproducible cost-model harness in src/test/java/org/example/videoclips/perf/CostModelBenchmarkHarness.java:1 that turns the checked-in FFmpeg and object-storage benchmark baselines into per-source-minute estimates
under explicit planning assumptions. The checked-in companion doc is docs/cost-model-by-video-minute.md:1, and it now includes the modeled baseline table:

  - exact-veryfast-720p: 0.000754 USD / source min
  - exact-medium-720p: 0.000816 USD / source min
  - exact-veryfast-720p-slow-storage: 0.000802 USD / source min
2026-07-09 19:04:23 +02:00
JSLMPR 632959104b • The next step is done and the plan is updated. Autoscaling policies is now marked complete in docs/video-clipping-service-implementation-plan.md:717.
I added autoscaling-ready queue metrics in src/main/java/org/example/videoclips/observability/DatabaseQueueMetricsBinder.java:13, backed by new queue repository counters, and enabled Prometheus scraping via src/main/
  resources/application.properties:3 plus the Prometheus registry dependency in pom.xml:43. The policy itself is documented in docs/autoscaling-policies.md:1, including worker/API scaling rules and a sample KEDA ScaledObject.
  Coverage for the new gauges is in src/test/java/org/example/videoclips/observability/DatabaseQueueMetricsBinderTest.java:14.
2026-07-09 19:00:31 +02:00
JSLMPR 5565298351 • I completed the next plan item and updated the checklist. Queue visibility-timeout tuning is now marked done in docs/video-clipping-service-implementation-plan.md:716.
The main change is in src/main/java/org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapter.java:52: the DB queue now reclaims stale PROCESSING messages after a configurable visibility timeout instead of leaving them
  stuck forever after a worker crash. I added video-clipping.database-queue.visibility-timeout-ms with a default of 900000 ms in src/main/java/org/example/videoclips/config/VideoClippingProperties.java:171 and src/main/
  resources/application.properties:19, plus coverage for stale-claim recovery in src/test/java/org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapterTest.java:91. I also added the tuning note and sizing rule in docs/
  queue-visibility-timeout-tuning.md:1.
2026-07-09 18:37:57 +02:00
JSLMPR f46055c972 • The next plan item is done and the plan is updated. Object-storage bandwidth tests is now marked complete in docs/video-clipping-service-implementation-plan.md:713.
I added a reproducible benchmark harness in src/test/java/org/example/videoclips/perf/ObjectStorageBandwidthBenchmarkHarness.java:17 that exercises ObjectStoragePort materialization and upload paths across a local-disk
  baseline plus throttled 100/50/25 MiB/s profiles. I also checked in the measured baseline and rerun command in docs/object-storage-bandwidth-benchmark-baseline.md:1. On this workspace, the measured throughput came out at
  roughly 1282/825 MiB/s for local disk, 93/89 MiB/s for the 100 MiB/s cap, 48/47 MiB/s for 50 MiB/s, and 24/24 MiB/s for 25 MiB/s on materialize/upload respectively.
2026-07-09 01:33:24 +02:00
JSLMPR 9ffe9bca5c I continued with the next plan step and updated the plan.
I completed Worker CPU/disk benchmarks by adding a reproducible benchmark harness at src/test/java/org/example/videoclips/perf/WorkerBenchmarkHarness.java:1 and checking in the resulting baseline at docs/worker-cpu-disk-
  benchmark-baseline.md:1. The harness measures synchronous worker wall time, current-thread CPU time, clip count, and local/uploaded output bytes for FAST and EXACT stub-processing scenarios, and writes the generated report to
  target/benchmarks/worker-cpu-disk-benchmark.md.

  The plan now marks that item complete in docs/video-clipping-service-implementation-plan.md:711. Verification also stayed green: mvn -q -Dtest=WorkerBenchmarkHarness test passed, and mvn -q test passed with the default suite
  plus the benchmark harness.
2026-07-09 01:25:04 +02:00
JSLMPR e18c2cd9a9 • I completed the next plan step and updated the plan. Security review is now marked done in docs/video-clipping-service-implementation-plan.md:701.
The security hardening I implemented was tenant isolation across the API surface. X-Tenant-Id is now enforced on asset reads, upload completion, asset/job event reads, clip listing, job reads, cancellation, deletion, and
  signed download URL creation. Cross-tenant access returns 403 via the new src/main/java/org/example/videoclips/application/ForbiddenException.java:1 and handler wiring in src/main/java/org/example/videoclips/api/
  ApiExceptionHandler.java:1. I also stopped exposing providerUploadId from the upload-session read response in src/main/java/org/example/videoclips/application/VideoAssetService.java:224, since that provider identifier is
  internal metadata.

  Verification: mvn -q test passed.

  - TenantQuotaControllerTest: 1/1
  - VideoAssetControllerTest: 11/11
  - RetentionCleanupJobTest: 2/2
  - DatabaseBackedClipJobQueueAdapterTest: 2/2

  The production-hardening section of the plan is now fully checked off.
2026-07-09 01:19:43 +02:00
JSLMPR a660b7c1d8 I completed the next step, Full application/problem+json error model, and updated the plan in docs/video-clipping-service-implementation-plan.md:701.
The main change is in src/main/java/org/example/videoclips/api/ApiExceptionHandler.java:1. It now consistently returns problem details for:

  - validation errors
  - malformed JSON
  - unsupported request content type
  - method not allowed
  - quota/conflict/not-found/media-type domain exceptions
  - unexpected internal errors

  I also extended src/test/java/org/example/videoclips/api/VideoAssetControllerTest.java:1 to assert application/problem+json and cover malformed JSON, unsupported request content type, and method-not-allowed responses.
2026-07-09 01:14:38 +02:00
JSLMPR 1737d8b220 I finished the missing part: retryable DB-queue failures no longer become terminal job failures on the first exception. ClipProcessor now supports non-terminal queue retries, the DB queue adapter reschedules retries and only
marks the job FAILED when the message actually moves to DLQ, and retry/DLQ events are recorded at the job level. The key changes are in src/main/java/org/example/videoclips/processing/ClipProcessor.java:37 and src/main/java/
  org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapter.java:18.

  I also kept the queue tests aligned in src/test/java/org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapterTest.java:1, reran mvn -q test, and the suite passed:

  - TenantQuotaControllerTest: 1/1
  - VideoAssetControllerTest: 7/7
  - RetentionCleanupJobTest: 2/2
  - DatabaseBackedClipJobQueueAdapterTest: 2/2

  The plan is updated accordingly in docs/video-clipping-service-implementation-plan.md:701, with Retry and DLQ handling now marked complete. The next unfinished step is Full application/problem+json error model.
2026-07-09 01:10:53 +02:00
JSLMPR 1bd879f1e2 I completed the next plan step, Tenant quotas, and updated the plan to mark it done in docs/video-clipping-service-implementation-plan.md:701.
The implementation adds tenant-aware assets/jobs plus a configurable per-tenant active-job quota. The main enforcement is in src/main/java/org/example/videoclips/application/VideoAssetService.java:165, backed by tenant fields
  added to the domain/persistence model and migration src/main/resources/db/migration/V6__tenant_quota_support.sql:1. Requests can set X-Tenant-Id on asset creation, quota config lives in src/main/java/org/example/videoclips/
  config/VideoClippingProperties.java:39, and quota violations now return 429 via src/main/java/org/example/videoclips/api/ApiExceptionHandler.java:44.
2026-07-09 01:07:07 +02:00
JSLMPR 8548542248 • I updated the milestone section in docs/video-clipping-service-implementation-plan.md:688 to mark what is already done and to show Retry and DLQ handling as in progress rather than untouched.
I also started that next step in code. The database-backed queue now retries failed jobs with configurable backoff and moves messages to a terminal DLQ status after the configured max attempts in src/main/java/org/example/
  videoclips/queue/DatabaseBackedClipJobQueueAdapter.java:48. The new queue settings live in src/main/java/org/example/videoclips/config/VideoClippingProperties.java:133, and I added focused coverage in src/test/java/org/
  example/videoclips/queue/DatabaseBackedClipJobQueueAdapterTest.java:1.

  Verification: mvn -q test passed.

  - VideoAssetControllerTest: 7/7
  - RetentionCleanupJobTest: 2/2
  - DatabaseBackedClipJobQueueAdapterTest: 2/2
2026-07-09 00:59:22 +02:00
JSLMPR 0d45f898f7 I continued with the security-review step from the plan and tightened the API contract so internal storage locations no longer leak out of normal responses.
Changes:

  - src/main/java/org/example/videoclips/application/VideoAssetService.java:401 no longer exposes sourceObjectKey on asset reads or objectKey on clip listings.
  - src/main/java/org/example/videoclips/processing/ClipProcessor.java:64 now records a sanitized SOURCE_MATERIALIZED event message instead of logging the worker-local path.
  - src/test/java/org/example/videoclips/api/VideoAssetControllerTest.java:67 now asserts those fields are absent and that job events do not contain uploads/ or tmp/.
2026-07-09 00:55:35 +02:00
JSLMPR 73070824df I changed the signed clip download flow so it uses the clip’s persisted objectKey instead of deriving a fake path from clipId. The fix is in src/main/java/org/example/videoclips/application/
VideoAssetService.java, src/main/java/org/example/videoclips/storage/ObjectStoragePort.java, src/main/java/org/example/videoclips/storage/InMemoryObjectStorageAdapter.java, and src/main/java/org/
  example/videoclips/storage/S3ObjectStorageAdapter.java.

  I also added focused coverage for this slice:

  - API test for generating a signed URL for an actual produced clip in src/test/java/org/example/videoclips/api/VideoAssetControllerTest.java
  - cleanup job tests for expired clip/object deletion and disabled cleanup in src/test/java/org/example/videoclips/operations/RetentionCleanupJobTest.java
2026-07-09 00:34:14 +02:00
JSLMPR 8cb232d70e Assets and clips now carry expiration timestamps in the domain model:
- src/main/java/org/example/videoclips/domain/VideoAsset.java
  - src/main/java/org/example/videoclips/domain/Clip.java

  That metadata is mapped through the in-memory and JPA repository paths, including:

  - src/main/java/org/example/videoclips/infrastructure/InMemoryVideoAssetRepository.java
  - src/main/java/org/example/videoclips/persistence/JpaVideoClippingRepository.java
  - src/main/java/org/example/videoclips/persistence/entity/VideoAssetEntity.java
  - src/main/java/org/example/videoclips/persistence/entity/ClipEntity.java

  I also added scheduled retention cleanup in src/main/java/org/example/videoclips/operations/RetentionCleanupJob.java, with configuration in src/main/java/org/example/videoclips/config/
  VideoClippingProperties.java and src/main/resources/application.properties. Right now it soft-expires assets by marking them deleted when their retention time passes. Clip retention timestamps
  are now assigned by both clipper adapters so the service has real expiration data to work with.

  What this does not do yet is physically delete expired clip objects or original source objects from object storage. The retention job is metadata-aware now, but object-store deletion still needs
  to be added through the storage port as the next step.
2026-07-09 00:28:05 +02:00
JSLMPR 3d961f2adf The new cleanup job is in src/main/java/org/example/videoclips/operations/LocalArtifactCleanupJob.java. It runs on a schedule and removes expired files from:
- the FFmpeg input directory
  - the FFmpeg output directory
  - tmp/in-memory-storage
  - tmp/stub-output

  The schedule and retention window are now configurable through src/main/java/org/example/videoclips/config/VideoClippingProperties.java and src/main/resources/application.properties via:

  - video-clipping.cleanup.enabled
  - video-clipping.cleanup.local-artifact-poll-interval-ms
  - video-clipping.cleanup.local-artifact-retention-hours

  This closes the first retention slice from the plan on the worker side. It does not yet delete expired original videos or clips from real object storage, and it does not do database-driven
  retention policies. That would be the next cleanup step.
2026-07-09 00:23:41 +02:00