Brought-in footage plays at the project's rate

The new symbol gets project-rate frames covering the same wall-clock length,
and its root and sound map them back onto the source's frames.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Olive Vaughn 2026-09-30 01:11:32 -04:00
parent 4b8123d5e2
commit 1ac21fdcab
2 changed files with 26 additions and 6 deletions

View file

@ -71,6 +71,21 @@
[clip frozen label footage-id range] [clip frozen label footage-id range]
(let [{c :clip ids :ids} (symbols clip frozen [:main] {:main (symbol-id label)}) (let [{c :clip ids :ids} (symbols clip frozen [:main] {:main (symbol-id label)})
sid (ids :main) sid (ids :main)
source-fps (:fps frozen)
project-fps (:fps clip)
;; The new symbol is played by the receiving project's clock. Keep its
;; wall-clock duration by giving it project-rate frames, while its root
;; maps those frames back onto the source timeline. A 30fps source in a
;; 12fps project therefore has 2.5 source frames per project frame.
source-rate (if (and (number? source-fps) (pos? source-fps)
(number? project-fps) (pos? project-fps))
(/ source-fps project-fps)
1)
output-frames (max 1 (js/Math.ceil (/ (clip/frames c sid) source-rate)))
c (-> c
(assoc-in [:symbols sid :frames] output-frames)
(update-in [:symbols sid :nodes :root :time]
#(assoc (or % {}) :mode :map :at 0 :rate source-rate)))
tracked? (and (nil? (:analysis clip)) tracked? (and (nil? (:analysis clip))
(every? #(= % (ids %)) (keys (:subjects frozen))))] (every? #(= % (ids %)) (keys (:subjects frozen))))]
{:sid sid {:sid sid
@ -81,7 +96,10 @@
{:id :sound :name "sound" :kind :audio :parent nil {:id :sound :name "sound" :kind :audio :parent nil
:z "z-sound" :source {:footage footage-id} :z "z-sound" :source {:footage footage-id}
;; Source frame `start` plays on the symbol's 0. ;; Source frame `start` plays on the symbol's 0.
:span range :time {:mode :map :at (- (first range)) :rate 1}})) :span range
:time {:mode :map
:at (/ (- (first range)) source-rate)
:rate source-rate}}))
tracked? (-> (assoc :analysis (:analysis frozen)) tracked? (-> (assoc :analysis (:analysis frozen))
(update :subjects merge (:subjects frozen)) (update :subjects merge (:subjects frozen))
(update :features merge (:features frozen)) (update :features merge (:features frozen))

View file

@ -5,6 +5,7 @@
detector's identity comes from the server too, because it goes into the content detector's identity comes from the server too, because it goes into the content
address of every block this produces." address of every block this produces."
(:require [arthur.domain.bring :as bring] (:require [arthur.domain.bring :as bring]
[arthur.domain.clip :as clip]
[arthur.events.edit :as edit] [arthur.events.edit :as edit]
[arthur.events.playback :as pb] [arthur.events.playback :as pb]
[arthur.flow.detect :as detect] [arthur.flow.detect :as detect]
@ -432,6 +433,8 @@
{:keys [clip sid tracked?]} {:keys [clip sid tracked?]}
(bring/take (:clip (store/entry (:clip/current db))) (:clip built) (bring/take (:clip (store/entry (:clip/current db))) (:clip built)
name footage-id range) name footage-id range)
imported-frames (clip/frames clip sid)
source-fps (get-in built [:clip :fps])
db (edit/edit-entry db (edit/edit-entry
db db
#(cond-> (bring/placed % clip (:store built) sid host frame uuid point) #(cond-> (bring/placed % clip (:store built) sid host frame uuid point)
@ -442,10 +445,9 @@
(assoc-in [:ui :selection] [:node host uuid [uuid]]) (assoc-in [:ui :selection] [:node host uuid [uuid]])
(update :footage merge (update :footage merge
{:loading? false {:loading? false
:status (str "made " name " · " (- (second range) (first range)) " frames" :status (str "made " name " · " imported-frames " frames at " fps " fps"
(when (not= fps source-fps)
(str " · sampled from " source-fps " fps"))
(when-not tracked? (when-not tracked?
" · as drawings: this project already tracks other footage") " · as drawings: this project already tracks other footage"))}))
(when (not= fps (get-in built [:clip :fps]))
(str " · footage is " (get-in built [:clip :fps])
" fps, this project " fps)))}))
:dispatch [::pb/refresh-clock]}))) :dispatch [::pb/refresh-clock]})))