videobook 0.2.3 → 0.2.4

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +3 -2
  3. package/dist/command-reference.js +16 -2
  4. package/dist/env-secrets.js +6 -4
  5. package/dist/jobs/complete-provider-task.js +7 -1
  6. package/dist/jobs/generate-media.js +4 -0
  7. package/dist/jobs/render-project.js +124 -31
  8. package/dist/media/adapters/index.js +4 -0
  9. package/dist/media/adapters/machgen.js +48 -0
  10. package/dist/media/adapters/types.js +1 -0
  11. package/dist/media/catalog.js +70 -0
  12. package/dist/media/complete.js +1 -1
  13. package/dist/media/frontier-gaps.js +49 -0
  14. package/dist/media/frontier.js +30 -0
  15. package/dist/media/listing.js +9 -2
  16. package/dist/media/machgen.js +261 -0
  17. package/dist/media/model-id.js +1 -1
  18. package/dist/media/preview.js +2 -0
  19. package/dist/media/prompt-dialects.js +2 -0
  20. package/dist/media/seedance-draft.js +48 -0
  21. package/dist/media/wire.js +3 -0
  22. package/dist/notebook-action-catalog.js +5 -0
  23. package/dist/one-password.js +13 -7
  24. package/dist/provider-status-link.js +1 -1
  25. package/dist/provider-task-status.js +6 -3
  26. package/dist/provider-usage.js +5 -3
  27. package/dist/queue.js +3 -0
  28. package/dist/tools/commands.js +1 -1
  29. package/dist/tools/estimate-cost.js +3 -1
  30. package/dist/tools/provider-key-status.js +2 -0
  31. package/dist/tools/reconcile-project-work.js +69 -1
  32. package/dist/usage-providers.js +4 -0
  33. package/dist/workspace-action-catalog.js +1 -1
  34. package/package.json +14 -13
  35. package/ui/assets/{alive-captions-4QySEGdt.js → alive-captions-Bp6dxosy.js} +1 -1
  36. package/ui/assets/confirm-bodies-Ds1HtaGc.js +1 -0
  37. package/ui/assets/{fullscreen-CzTnPPG5.js → fullscreen-BCeVHjvY.js} +1 -1
  38. package/ui/assets/{goal-ui-CosrK_ko.js → goal-ui-DbAGwgMN.js} +2 -2
  39. package/ui/assets/index-D1d-F1y9.js +37 -0
  40. package/ui/assets/index-DWfR79lA.css +1 -0
  41. package/ui/assets/{inspector-BN2fezh4.js → inspector-BJTC0luH.js} +1 -1
  42. package/ui/assets/{jobs-ui-C4Wgy6I1.js → jobs-ui-C1cbw-xG.js} +1 -1
  43. package/ui/assets/{music-video-BSj8SgbQ.js → music-video-CWtxPlxq.js} +1 -1
  44. package/ui/assets/ui-CXDi5Omq.js +2 -0
  45. package/ui/assets/vendor-BFupLz37.js +19 -0
  46. package/ui/assets/{vendor-flow-zBavaNEW.js → vendor-flow-CKiuzaeM.js} +1 -1
  47. package/ui/assets/{vendor-mcp-DQ7EusT9.js → vendor-mcp-DQEeVZH0.js} +1 -1
  48. package/ui/assets/videobook-J-j9bSjM.js +20 -0
  49. package/ui/index.html +12 -12
  50. package/ui/assets/confirm-bodies-Bw818V9J.js +0 -1
  51. package/ui/assets/index-C9xjFEGL.js +0 -37
  52. package/ui/assets/index-DzPAnCUj.css +0 -1
  53. package/ui/assets/ui-Cpr6zMTA.js +0 -2
  54. package/ui/assets/vendor-yctIZ9Dz.js +0 -19
  55. package/ui/assets/videobook-B5G0jMoi.js +0 -20
@@ -1 +1 @@
1
- import{a as d,b as Lt,j as t,c as _t}from"./vendor-react-Dj7D1fD4.js";import{ec as Ut,bw as Pt,b_ as $t,bv as ye}from"./videobook-B5G0jMoi.js";import{S as Ke,r as Ht,s as Ot,t as Kt,v as qt,w as Vt,x as Wt}from"./ui-Cpr6zMTA.js";import{X as Gt,aq as Xt,c as qe,ar as Zt,as as Yt,D as Jt,f as Qt,k as Ve,m as We,W as ei,a as Ge,w as ti,F as ii}from"./vendor-icons-CGqhCIXV.js";import"./vendor-yctIZ9Dz.js";import"./vendor-mcp-DQ7EusT9.js";import"./vendor-remotion-CH1HXrlc.js";import"./vendor-flow-zBavaNEW.js";const ie=[{label:"0.5×",value:"1/2",numerator:1,denominator:2},{label:"0.75×",value:"3/4",numerator:3,denominator:4},{label:"1×",value:"1/1",numerator:1,denominator:1},{label:"1.5×",value:"3/2",numerator:3,denominator:2},{label:"2×",value:"2/1",numerator:2,denominator:1}],ai=[{value:"media",label:"Media"},{value:"music",label:"Music"},{value:"autocut",label:"Auto-cut"}],ni=20,si=60;function ri(s){return[...s.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])')].filter(l=>l.getClientRects().length>0&&!l.closest("[hidden], [inert]"))}function x(s){return s.timelineStartFrame+s.durationFrames}const ae=$t;function Xe(s){return Math.max(ni,Math.min(si,Math.round(s)))}function li(s,l){const c=[...s].reverse().find(h=>h.frame<l),r=s.find(h=>h.frame>l);return{previous:c?.frame??null,next:r?.frame??null}}function oi(s,l){return l?s.clips.filter(c=>c.trackId===l).sort((c,r)=>c.timelineStartFrame-r.timelineStartFrame||c.clipId.localeCompare(r.clipId)):[]}function ci(s){if(!s||s.source.kind!=="timed")return"1/1";const l=s;return`${l.speed.numerator}/${l.speed.denominator}`}function di(s,l){if(s.source.kind!=="timed")return s.durationFrames;const c=s,r=c.source.range.durationTicks*c.source.range.timeBase.numerator/c.source.range.timeBase.denominator;return Math.max(1,Math.ceil(r*l))}function ui(s){const[l,c]=s.split("/").map(Number);if(!l||!c)return s;const r=l/c;return Number.isInteger(r)?`${r}×`:`${parseFloat(r.toFixed(2))}×`}function mi(s,l){const c=s.findIndex(r=>r.clipId===l.clipId);return c>=0?s[c+1]:void 0}function Ze(s,l,c){const r=l.findIndex(o=>o.clipId===s.clipId),h=r>0?l[r-1]:void 0,f=r>=0?l[r+1]:void 0;return{left:s.timelineStartFrame-(h?x(h):0),right:(f?f.timelineStartFrame:c)-x(s)}}function pi(s,l,c){if(s.source.kind!=="timed")return{before:s.timelineStartFrame,after:Number.MAX_SAFE_INTEGER};const r=s,h=r.speed.numerator/r.speed.denominator,f=r.source.range.timeBase.numerator/r.source.range.timeBase.denominator,o=r.source.range.startTick*f,w=(r.source.range.startTick+r.source.range.durationTicks)*f,ne=l?.duration??w,U=Math.floor(o*c/h),P=Math.floor(Math.max(0,ne-w)*c/h);return r.reverse?{before:P,after:U}:{before:U,after:P}}function fi(s){return/\.(avif|bmp|gif|jpe?g|png|webp)(?:$|\?)/i.test(s)}function bi(s){const l=_t.c(5),{asset:c}=s,r=c.thumbnailUrl??(c.mediaUrl&&fi(c.mediaUrl)?c.mediaUrl:null);if(r){let f;return l[0]!==r?(f=t.jsx("img",{src:r,alt:""}),l[0]=r,l[1]=f):f=l[1],f}if(c.mediaUrl){let f;return l[2]!==c.mediaUrl?(f=t.jsx("video",{src:c.mediaUrl,muted:!0,playsInline:!0,preload:"metadata",onLoadedMetadata:vi}),l[2]=c.mediaUrl,l[3]=f):f=l[3],f}let h;return l[4]===Symbol.for("react.memo_cache_sentinel")?(h=t.jsx(ii,{size:24}),l[4]=h):h=l[4],h}function vi(s){const l=s.currentTarget;l.duration>0&&(l.currentTime=Math.min(.12,l.duration*.15))}function hi(s,l){return s.status==="ready"||s.status==="applying"||s.status==="applied"?s.timelineLimitFrame:Math.max(1,...l.clips.map(x))}function wi({sequence:s,assets:l,audioArtifactId:c,setup:r,returnFocus:h,assembly:f,rhythm:o,address:w,initialFrame:ne=0,onFrameUpdate:U,onExport:P,onPlanDraft:Ye,onApplyDraft:Je,onApplySetup:Qe,onClose:se,onCommit:et,onCreateTrack:tt,onRefreshAssets:it,onRestore:Se,onReviewSetup:ke}){const $=d.useRef(null),at=d.useEffectEvent(se),[L,re]=d.useState(r.status!=="timeline"),[nt,Ie]=d.useState(34),[le,Ce]=d.useState({mode:"beats",fallback:"off"}),[st,we]=d.useState(!1),M=d.useRef(null),Ne=d.useRef(null),Me=d.useRef(null),[F,rt]=d.useState(ne),Fe=d.useCallback(e=>{rt(e),U(e)},[U]),[u,oe]=d.useState(null),[ce,lt]=d.useState(""),[C,q]=d.useState([]),ot=f.selectedClipId,N=f.selectClip,[Ee,E]=d.useState(null),[b,g]=d.useState(null),[Re,p]=d.useState(null),[de,V]=d.useState([]),[ue,W]=d.useState([]),[me,T]=d.useState(null),[G,H]=d.useState(()=>Ut(r.status)),O=l.find(e=>e.artifactId===(o.master?.source.artifactId??c)),S=[...s.tracks].sort((e,i)=>e.ordinal-i.ordinal).find(e=>e.kind==="video")??null,y=oi(s,S?.trackId??null),a=y.find(e=>e.clipId===ot)??null,X=d.useMemo(()=>new Map(l.map(e=>[e.artifactId,e])),[l]),Z=me?X.get(me):void 0,ct=d.useMemo(()=>l.flatMap(e=>e.mediaUrl?[{artifactId:e.artifactId,mediaUrl:e.mediaUrl}]:[]),[l]),pe=d.useMemo(()=>{const e=ce.trim().toLowerCase();return l.filter(i=>(i.type==="video"||i.type==="final")&&i.status==="ready"&&i.mediaUrl&&(!e||i.label.toLowerCase().includes(e)||i.artifactId.toLowerCase().includes(e)))},[l,ce]),v=o.master?o.master.timelineStartFrame+o.master.durationFrames:hi(r,s),j=s.frameRate.numerator/s.frameRate.denominator,fe=Math.max(0,...y.map(x)),Be=Math.max(0,fe-v),be=(r.status==="ready"||r.status==="applied"||r.status==="timeline")&&S!==null&&S.enabled&&!S.locked,_=a?Ee?.clipId===a.clipId?Ee:{clipId:a.clipId,startFrame:a.timelineStartFrame,endFrame:x(a)}:null,ve=a?X.get(a.source.artifactId):void 0,Te=a?pi(a,ve,j):{before:0,after:0},Y=a?y.findIndex(e=>e.clipId===a.clipId):-1,he=a?mi(y,a)?.timelineStartFrame??v:v,Ae=a?Ze(a,y,v):{left:0,right:0},dt=Y>0,ut=Y>=0&&Y<y.length-1,mt=dt||Ae.left>0,pt=ut||Ae.right>0,ft=!!(a&&he>x(a)),De=a?Math.max(0,a.timelineStartFrame-Te.before):0,ze=a?Math.min(v,x(a)+Te.after):v,J=ci(a),bt=ie.some(e=>e.value===J)?[...ie]:[{label:ui(J),value:J},...ie],Le=li(o.mapped,F),R=o.mapped.length>0,A=o.mapped.some(e=>e.bar),vt=o.analysis?.barSource==="estimated"&&!o.rhythm.settings.correction,K=o.status==="queued"||o.status==="analyzing",xe=le.mode==="bars"&&!A?le.fallback:le.mode,B=xe==="beats"&&!R||xe==="bars"&&!A?"off":xe,_e=[{value:"off",label:"Off"},{value:"beats",label:"Beats",disabled:!R,title:R?"Snap edits to beats":"Analyze beats or set a beat grid first"},{value:"bars",label:"Bars",disabled:!R,title:A?"Snap edits to bar starts":"Set up bar starts to enable bar snapping"}];function Q(e="beats"){N(null),re(!0),H("music"),e==="beats"&&we(!!o.master),Ce({mode:e,fallback:B}),e==="bars"&&requestAnimationFrame(()=>{const i=$.current?.querySelector('input[name="beats-per-bar"]');i?.focus(),i?.scrollIntoView({block:"nearest"})})}function Ue(e){if(e==="bars"&&!A){Q(e);return}Ce({mode:e,fallback:"off"})}d.useEffect(()=>{const e=$.current;e?.showModal(),e?.querySelector(".music-video-close")?.focus();const i=n=>{if(n.isComposing||n.keyCode===229||!(n.target instanceof Element)||n.target.closest("dialog")!==e)return;if(n.key==="Escape"){n.preventDefault(),at();return}if(n.key!=="Tab"||!e)return;const m=ri(e),I=m[0],D=m[m.length-1];n.shiftKey&&document.activeElement===I?(n.preventDefault(),D?.focus()):!n.shiftKey&&document.activeElement===D&&(n.preventDefault(),I?.focus())};return document.addEventListener("keydown",i),()=>{document.removeEventListener("keydown",i),e?.close(),Pt(h)}},[h]);const k=async(e,i)=>{if(b||u)return!1;if(!S)return p("Create a main video track before editing clips"),!1;if(r.status!=="ready"&&r.status!=="applied"&&r.status!=="timeline")return p("Wait for the soundtrack duration before editing clips"),!1;g(e),p(null);try{const n=await et(i,s);return V(m=>[...m,{beforeRevision:n.beforeRevision,afterRevision:n.sequence.revision}]),W([]),E(null),!0}catch(n){return p(n instanceof Error?n.message:String(n)),!1}finally{g(null)}},ee=e=>{const i=Math.max(0,Math.min(Math.max(v,...s.clips.map(x))-1,Math.round(e)));T(null),Fe(i),M.current?.seekTo(i)},ht=e=>{T(null),N(e.clipId),s.tracks.find(i=>i.trackId===e.trackId)?.kind==="audio"&&H("music"),E({clipId:e.clipId,startFrame:e.timelineStartFrame,endFrame:x(e)}),ee(e.timelineStartFrame)},xt=e=>{T(e),N(null),q(i=>i.includes(e)?i.filter(n=>n!==e):[...i,e])},gt=async()=>{!S||C.length===0||!await k("Adding clips",{kind:"append_clips",track_id:S.trackId,artifact_ids:C,timeline_limit_frame:o.master?v:Math.max(v,fe+C.reduce((i,n)=>i+Math.ceil((X.get(n)?.duration??0)*j),0)),fit:"source",visual_fit:"fit"})||(q([]),T(null))},jt=async e=>{S&&await k("Reordering clips",{kind:"reorder_clips",track_id:S.trackId,clip_ids:e,timeline_limit_frame:v})},yt=async e=>{if(!a||!S)return;const i=y.findIndex(z=>z.clipId===a.clipId),n=i+e;if(n>=0&&n<y.length){const z=y.map(zt=>zt.clipId),[Oe]=z.splice(i,1);if(!Oe)return;z.splice(n,0,Oe),await jt(z);return}const m=Ze(a,y,v),I=Math.max(1,Math.round(j)),D=e<0?-Math.min(I,m.left):Math.min(I,m.right);D!==0&&await k("Moving clip",{kind:"move",clip_id:a.clipId,track_id:S.trackId,timeline_start_frame:a.timelineStartFrame+D})},St=async()=>{if(!a||he<=x(a))return;const e=he-a.timelineStartFrame;if(a.source.kind!=="timed"){await k("Stretching clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:a.timelineStartFrame,duration_frames:e,edge:"end",ripple:!1,timeline_limit_frame:v});return}const i=a,n=di(a,j);await k("Stretching clip",{kind:"speed",clip_id:a.clipId,numerator:n,denominator:e,reverse:i.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},te=async(e,i,n)=>{if(!(!a||n<=i)&&!(i===a.timelineStartFrame&&n===x(a))){if(B!=="off"&&(e==="start"?i=ye(i,o.mapped,B):n=ye(n,o.mapped,B)),n<=i){p("Choose distinct beat boundaries or turn snapping off");return}await k("Trimming clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:i,duration_frames:n-i,edge:e,ripple:!1,timeline_limit_frame:v})}},ge=async()=>{if(!a||F<=a.timelineStartFrame||F>=x(a)){p("Place the playhead inside the selected clip before cutting");return}const e=ye(F,o.mapped,B);if(e<=a.timelineStartFrame||e>=x(a)){p("Choose a beat inside the selected clip, or turn snapping off");return}await k("Cutting clip",{kind:"split",clip_id:a.clipId,split_frame:e}),N(null)},Pe=async()=>{a&&(await k("Deleting clip",{kind:"delete",clip_id:a.clipId,ripple:!1}),N(null))},kt=async e=>{if(!a||a.source.kind!=="timed")return;const i=ie.find(z=>z.value===e),[n,m]=e.split("/").map(Number),I=i??(n&&m?{numerator:n,denominator:m}:null);if(!I)return;const D=a;await k("Retiming clip",{kind:"speed",clip_id:a.clipId,numerator:I.numerator,denominator:I.denominator,reverse:D.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},$e=async()=>{const e=de[de.length-1];if(!(!e||b)){g("Undoing edit"),p(null);try{await Se(e.beforeRevision,s.revision),V(i=>i.slice(0,-1)),W(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},He=async()=>{const e=ue[ue.length-1];if(!(!e||b)){g("Redoing edit"),p(null);try{await Se(e.afterRevision,s.revision),W(i=>i.slice(0,-1)),V(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},It=(e,i)=>{if(e==="split"&&ge(),e==="delete"&&Pe(),e==="undo"&&$e(),e==="redo"&&He(),e==="search"&&(re(!0),H("media"),requestAnimationFrame(()=>Ne.current?.focus())),e==="zoom-in"&&$.current?.querySelector('[aria-label="Zoom timeline in"]')?.click(),e==="zoom-out"&&$.current?.querySelector('[aria-label="Zoom timeline out"]')?.click(),e==="mark-in"&&a){const n=_?.endFrame??x(a);i<n&&(E({clipId:a.clipId,startFrame:i,endFrame:n}),te("start",i,n))}if(e==="mark-out"&&a){const n=_?.startFrame??a.timelineStartFrame;i>n&&(E({clipId:a.clipId,startFrame:n,endFrame:i}),te("end",n,i))}},Ct=async()=>{if(!(r.status!=="ready"||b)){g("Applying soundtrack"),p(null);try{await Qe()}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},wt=async e=>{if(!b){g("Creating soundtrack track"),p(null);try{const i=await tt(e);e==="audio"&&await ke(i)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Nt=e=>{if(e.defaultPrevented||e.nativeEvent.isComposing||e.nativeEvent.keyCode===229||e.target.closest('input, textarea, select, [contenteditable="true"], .canonical-player'))return;if(M.current){M.current.handleKeyDown(e);return}const n=Me.current,m=e.key.toLowerCase();!n||m!==" "&&m!=="k"||(e.preventDefault(),n.paused?n.play().catch(()=>{}):n.pause())},Mt=async e=>{if(!b){g("Planning draft"),p(null),M.current?.pause();try{const i=await Ye(e,s);oe(i),T(null),ee(e.start_frame)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Ft=async()=>{if(!(!u||b||u.uncovered.length)){g("Applying draft"),p(null),M.current?.pause();try{const e=await Je(u);V(i=>[...i,{beforeRevision:e.beforeRevision,afterRevision:e.sequence.revision}]),W([]),oe(null),N(null)}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},je=!be||!!b||!!u,Et=e=>{if(e.button!==0)return;const i=e.currentTarget;i.setPointerCapture(e.pointerId);const n=I=>{Ie(Xe((window.innerHeight-I.clientY)/window.innerHeight*100))},m=()=>{i.removeEventListener("pointermove",n),i.removeEventListener("pointerup",m),i.removeEventListener("pointercancel",m)};i.addEventListener("pointermove",n),i.addEventListener("pointerup",m),i.addEventListener("pointercancel",m)},Rt=e=>{const i=e.key==="ArrowUp"?2:e.key==="ArrowDown"?-2:0;i&&(e.preventDefault(),e.stopPropagation(),Ie(n=>Xe(n+i)))},Bt=()=>{M.current?.pause(),oe(null)},Tt=C.flatMap(e=>{const i=X.get(e);return i?[i]:[]}),At=A?vt?` · Estimated ${o.analysis?.beatsPerBar}-beat bars`:"":" · Bars not set",Dt=K?"Analyzing beats…":R?`${o.mapped.length} beats${o.analysis?.lowConfidence&&!o.rhythm.settings.correction?" · Review timing":""}${At}`:o.status==="no-beats"?"Analysis complete · No reliable beats found · Set a beat grid":o.master?"Analyze the soundtrack to enable snapping":"Choose a soundtrack for snapping";return Lt.createPortal(t.jsxs("dialog",{className:"music-video-editor timeline-preview-fullscreen","aria-label":w?`Timeline preview ${w}`:"Music video editor",style:{"--music-timeline-height":`${nt}dvh`},onCancel:e=>{e.preventDefault(),se()},ref:$,tabIndex:-1,onKeyDown:Nt,children:[t.jsxs("header",{className:"music-video-editor-header",children:[t.jsx("button",{className:"music-video-close mv-icon",type:"button",onClick:se,"aria-label":w?"Close timeline preview":"Close music video editor",children:t.jsx(Gt,{size:20})}),t.jsxs("div",{className:"music-video-title",children:[t.jsxs("h1",{children:[w?t.jsxs(t.Fragment,{children:["Timeline ",t.jsx("code",{children:w})]}):O?.label??"Music video",u&&t.jsx("span",{className:"mv-draft-badge",children:"Draft preview"})]}),t.jsxs("p",{children:[s.width,"×",s.height," · ",parseFloat(j.toFixed(2))," fps · ",ae(v,j)]})]}),t.jsxs("div",{className:"music-video-header-actions",children:[t.jsxs("button",{type:"button",className:"mv-quiet mv-tools-toggle","aria-pressed":L,"aria-label":L?"Hide tools":"Show tools",onClick:()=>re(e=>!e),children:[t.jsx(Xt,{size:16})," ",t.jsx("span",{children:L?"Hide tools":"Show tools"})]}),u?t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"mv-draft-note",children:"Nothing changes until you apply."}),t.jsx("button",{type:"button",disabled:!!b,onClick:Bt,children:"Discard draft"}),t.jsxs("button",{type:"button",className:"mv-apply",disabled:!!b||u.uncovered.length>0,onClick:()=>{Ft()},children:[t.jsx(qe,{size:16})," Apply draft"]})]}):t.jsxs(t.Fragment,{children:[t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||de.length===0,onClick:()=>{$e()},children:[t.jsx(Zt,{size:16})," Undo"]}),t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||ue.length===0,onClick:()=>{He()},children:[t.jsx(Yt,{size:16})," Redo"]}),t.jsxs("button",{type:"button",className:"mv-primary",onClick:P,children:[t.jsx(Jt,{size:16})," Export"]})]})]})]}),t.jsxs("main",{className:["music-video-editor-main",L?"":"tools-hidden",a||u?"inspecting":""].filter(Boolean).join(" "),children:[t.jsxs("aside",{className:"music-video-library","aria-label":"Library",hidden:!L,children:[t.jsx("div",{className:"music-video-library-tabs",role:"tablist","aria-label":"Library views",children:ai.map(e=>t.jsx("button",{type:"button",role:"tab",id:`mv-tab-${e.value}`,"aria-controls":`mv-panel-${e.value}`,"aria-selected":G===e.value,onClick:()=>H(e.value),children:e.label},e.value))}),t.jsxs("section",{className:"music-video-source-panel",role:"tabpanel",id:"mv-panel-media","aria-labelledby":"mv-tab-media",hidden:G!=="media",children:[t.jsxs("div",{className:"mv-panel-head",children:[t.jsxs("label",{className:"music-video-search",children:[t.jsx(Qt,{size:15}),t.jsx("input",{ref:Ne,value:ce,onChange:e=>lt(e.target.value),placeholder:"Search this book","aria-label":"Search source clips"})]}),t.jsx("button",{type:"button",className:"mv-icon","aria-label":"Refresh media",title:"Refresh media",onClick:()=>{it().catch(e=>p(String(e)))},children:t.jsx(Ve,{size:15})})]}),t.jsxs("div",{className:"mv-panel-meta",children:[t.jsxs("span",{children:[C.length," of ",pe.length," selected"]}),C.length>0&&t.jsx("button",{type:"button",className:"mv-link",onClick:()=>q([]),children:"Clear"})]}),t.jsxs("div",{className:"music-video-source-list",children:[pe.map(e=>{const i=C.indexOf(e.artifactId),n=me===e.artifactId;return t.jsxs("button",{type:"button",className:[i>=0?"selected":"",n?"previewing":""].filter(Boolean).join(" "),"aria-pressed":i>=0,"aria-label":e.label,onClick:()=>xt(e.artifactId),children:[t.jsxs("span",{className:"music-video-source-thumb",children:[t.jsx(bi,{asset:e}),i>=0&&t.jsx("i",{children:i+1}),e.duration!==null&&t.jsx("small",{children:ae(Math.round(e.duration*j),j)})]}),t.jsx("span",{className:"music-video-source-name",title:e.label,children:e.label})]},e.artifactId)}),pe.length===0&&t.jsx("p",{children:"No ready video sources match this search."})]}),t.jsxs("footer",{className:"mv-panel-foot",children:[t.jsxs("button",{type:"button",className:"mv-primary music-video-add-selected",disabled:je||C.length===0,onClick:()=>{gt()},children:[t.jsx(We,{size:15})," Add ",C.length||""," to end"]}),t.jsxs("button",{type:"button",disabled:C.length===0,onClick:()=>H("autocut"),children:[t.jsx(ei,{size:15})," Auto-cut…"]})]})]}),t.jsxs("section",{className:"mv-music-panel",role:"tabpanel",id:"mv-panel-music","aria-labelledby":"mv-tab-music",hidden:G!=="music",children:[t.jsxs("div",{className:"music-video-setup-card","data-status":r.status,children:[t.jsxs("span",{className:"mv-kicker",children:[t.jsx(Ge,{size:13})," Soundtrack",O?` · ${O.label}`:""]}),r.status==="loading"&&t.jsx("p",{children:"Building the exact canonical setup plan…"}),r.status==="needs-audio-track"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{children:r.message}),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{wt("audio")},children:[t.jsx(We,{size:15})," Create soundtrack track"]})]}),(r.status==="ready"||r.status==="applying")&&t.jsxs(t.Fragment,{children:[t.jsx("strong",{children:r.summary}),t.jsxs("p",{children:[r.operationCount," atomic operations · ends at ",ae(r.timelineLimitFrame,j)]}),r.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{Ct()},children:[t.jsx(Ge,{size:15})," Apply soundtrack"]})]}),r.status==="applied"&&t.jsxs("strong",{className:"music-video-applied",children:[t.jsx(qe,{size:15})," Soundtrack applied"]}),r.status==="error"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"music-video-error",children:r.message}),t.jsxs("button",{type:"button",disabled:!!b,onClick:()=>{ke()},children:[t.jsx(Ve,{size:15})," Review again"]})]})]}),t.jsxs("div",{className:"mv-control",children:[t.jsx("span",{children:"Snap edits to"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),t.jsx("p",{className:"mv-hint",children:"Hold Alt while dragging to ignore snapping."})]}),t.jsx(Ht,{rhythm:o,sequence:s,assets:l,frame:F,correctionsOpen:st,onCorrectionsOpenChange:we})]}),t.jsx("section",{className:"mv-autocut-panel",role:"tabpanel",id:"mv-panel-autocut","aria-labelledby":"mv-tab-autocut",hidden:G!=="autocut",children:t.jsx(Ot,{sources:Tt,trackId:S?.trackId??null,startFrame:o.master?.timelineStartFrame??0,endFrame:v,fps:j,hasBars:A,busy:!!b,draft:u,onPlan:e=>{Mt(e)},onOrder:q})})]}),t.jsxs("section",{className:"music-video-preview-panel timeline-preview-body","aria-label":"Program monitor",children:[t.jsx("div",{className:"mv-monitor",children:Z?.mediaUrl?t.jsxs("div",{className:"music-video-source-preview",children:[t.jsx("video",{ref:Me,src:Z.mediaUrl,controls:!0,autoPlay:!0,muted:!0,playsInline:!0},Z.artifactId),t.jsxs("p",{children:[t.jsxs("span",{children:["Source · ",Z.label]}),t.jsx("button",{type:"button",onClick:()=>T(null),children:"Show sequence"})]})]}):t.jsx(Kt,{ref:M,sequence:u?.sequence??s,assets:ct,onFrameUpdate:Fe,initialFrame:F,presentation:"preview",allowFullscreen:!1,editingEnabled:!u,onKeyboardAction:It})}),t.jsx(qt,{frame:F,durationFrames:Math.max(v,fe),fps:j,previousBeat:Le.previous,nextBeat:Le.next,onTogglePlay:()=>{T(null),M.current?.togglePlay()},onSeek:ee})]}),t.jsxs("aside",{className:"music-video-inspector","aria-label":"Inspector",hidden:!L,children:[a&&!u&&t.jsx("button",{type:"button",className:"mv-link mv-back",onClick:()=>N(null),children:"← Back to library"}),u?t.jsxs("div",{className:"mv-draft-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Draft review"}),t.jsx("strong",{children:u.plan.summary}),t.jsxs("p",{children:[u.shots.length," shots · replaces ",u.preview.diff.removedClipIds.length," clips"]}),u.uncovered.length>0&&t.jsx("p",{className:"music-video-error",children:"Gaps remain, so the draft can't be applied. Allow repeated footage or add sources in Auto-cut."}),u.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsx("p",{className:"mv-hint",children:"The full shot list is in Auto-cut."})]}):a&&_?t.jsx(Vt,{clip:a,label:ve?.label??"Clip",thumbnailUrl:ve?.thumbnailUrl??null,index:Y+1,count:y.length,fps:j,trimStart:_.startFrame,trimEnd:_.endFrame,trimMin:De,trimMax:Math.max(_.endFrame,ze),speed:J,speedOptions:bt,retimable:a.source.kind==="timed",busy:!!b,editsDisabled:je,canMoveEarlier:mt,canMoveLater:pt,canStretch:ft,onTrim:(e,i,n)=>{E({clipId:a.clipId,startFrame:i,endFrame:n}),te(e,i,n)},onSpeed:e=>{kt(e)},onFit:e=>{k("Fitting clip",{kind:"transform",clip_id:a.clipId,fit:e})},onSplit:()=>{ge()},onStretch:()=>{St()},onMove:e=>{yt(e)},onDelete:()=>{Pe()}}):t.jsxs("div",{className:"mv-sequence-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Sequence"}),t.jsxs("dl",{children:[t.jsx("dt",{children:"Frame"}),t.jsxs("dd",{children:[s.width," × ",s.height]}),t.jsx("dt",{children:"Rate"}),t.jsxs("dd",{children:[parseFloat(j.toFixed(2))," fps"]}),t.jsx("dt",{children:"Length"}),t.jsx("dd",{children:ae(v,j)}),t.jsx("dt",{children:"Clips"}),t.jsx("dd",{children:y.length})]}),y.length>0?t.jsx("p",{children:"Select a clip on the timeline to trim, retime or delete it."}):t.jsxs("ol",{className:"mv-steps",children:[t.jsx("li",{children:"Pick footage in Media"}),t.jsx("li",{children:"Choose a soundtrack in Music"}),t.jsx("li",{children:"Auto-cut, or add clips and trim by hand"})]})]})]}),t.jsxs("section",{className:"music-video-timeline-panel","aria-label":"Music video timeline",children:[t.jsx("button",{type:"button",className:"mv-resize-handle","aria-label":"Resize timeline",title:"Drag to resize the timeline (↑/↓)",onPointerDown:Et,onKeyDown:Rt}),t.jsx(Wt,{sequence:u?.sequence??s,assets:l,assembly:f,disabled:!!b||!!u,frame:F,address:w??"",onSeek:ee,onSelectClip:ht,onExport:P,presentation:"preview",onMoveClip:be?(e,i)=>{k("Moving clip",{kind:"move",clip_id:e.clipId,track_id:e.trackId,timeline_start_frame:i})}:void 0,onRemoveClip:e=>{k("Removing clip",{kind:"remove_clip",clip_id:e.clipId,ripple:!1})},onTrimClip:be?(e,i,n,m)=>{e.clipId===a?.clipId&&(E({clipId:e.clipId,startFrame:n,endFrame:m}),te(i,n,m))}:void 0,trimBounds:a?{min:De,max:Math.max(x(a),ze)}:void 0,rhythm:{masterClipId:o.master?.clipId??null,markers:o.mapped,analysis:o.analysis,snap:B},toolbar:t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Snap"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),!o.master&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Choose soundtrack"}),o.master&&!R&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.analyze(!!o.analysis)},children:o.analysis?"Analyze again":"Analyze beats"}),K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.cancel()},children:"Cancel analysis"}),o.master&&!R&&o.analysis&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Set beat grid"}),R&&!A&&t.jsx("button",{type:"button",disabled:o.busy||K,onClick:()=>Q("bars"),children:"Set bars"}),t.jsxs("button",{type:"button",disabled:je||!a,title:"Split the selected clip at the playhead (S)",onClick:()=>{ge()},children:[t.jsx(ti,{size:14})," Split"]}),o.master&&t.jsxs("span",{className:"music-master-name",title:O?.label,children:["♪ ",O?.label??"Soundtrack"]}),t.jsx("span",{role:"status",children:Dt})]})}),Be>0&&t.jsxs("p",{children:[Be," frames beyond soundtrack"]})]})]}),t.jsxs("footer",{className:"music-video-status","aria-live":"polite",children:[t.jsx("span",{children:b??(u?"Draft ready · review it, then apply or discard":"Saved")}),(Re||o.error)&&t.jsx("strong",{role:"alert",children:Re||o.error}),t.jsx("span",{className:"mv-shortcuts",children:"Space play · J/L shuttle · ←/→ frame · I/O trim · S split · Delete · ⌘Z undo"})]})]}),document.body)}export{wi as MusicVideoEditor};
1
+ import{a as d,b as Lt,j as t,c as _t}from"./vendor-react-Dj7D1fD4.js";import{ef as Ut,bx as Pt,b$ as $t,bw as ye}from"./videobook-J-j9bSjM.js";import{S as Ke,r as Ht,s as Ot,t as Kt,v as qt,w as Vt,x as Wt}from"./ui-CXDi5Omq.js";import{X as Gt,aq as Xt,c as qe,ar as Zt,as as Yt,D as Jt,f as Qt,k as Ve,m as We,W as ei,a as Ge,w as ti,F as ii}from"./vendor-icons-CGqhCIXV.js";import"./vendor-BFupLz37.js";import"./vendor-mcp-DQEeVZH0.js";import"./vendor-remotion-CH1HXrlc.js";import"./vendor-flow-CKiuzaeM.js";const ie=[{label:"0.5×",value:"1/2",numerator:1,denominator:2},{label:"0.75×",value:"3/4",numerator:3,denominator:4},{label:"1×",value:"1/1",numerator:1,denominator:1},{label:"1.5×",value:"3/2",numerator:3,denominator:2},{label:"2×",value:"2/1",numerator:2,denominator:1}],ai=[{value:"media",label:"Media"},{value:"music",label:"Music"},{value:"autocut",label:"Auto-cut"}],ni=20,si=60;function ri(s){return[...s.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])')].filter(l=>l.getClientRects().length>0&&!l.closest("[hidden], [inert]"))}function x(s){return s.timelineStartFrame+s.durationFrames}const ae=$t;function Xe(s){return Math.max(ni,Math.min(si,Math.round(s)))}function li(s,l){const c=[...s].reverse().find(h=>h.frame<l),r=s.find(h=>h.frame>l);return{previous:c?.frame??null,next:r?.frame??null}}function oi(s,l){return l?s.clips.filter(c=>c.trackId===l).sort((c,r)=>c.timelineStartFrame-r.timelineStartFrame||c.clipId.localeCompare(r.clipId)):[]}function ci(s){if(!s||s.source.kind!=="timed")return"1/1";const l=s;return`${l.speed.numerator}/${l.speed.denominator}`}function di(s,l){if(s.source.kind!=="timed")return s.durationFrames;const c=s,r=c.source.range.durationTicks*c.source.range.timeBase.numerator/c.source.range.timeBase.denominator;return Math.max(1,Math.ceil(r*l))}function ui(s){const[l,c]=s.split("/").map(Number);if(!l||!c)return s;const r=l/c;return Number.isInteger(r)?`${r}×`:`${parseFloat(r.toFixed(2))}×`}function mi(s,l){const c=s.findIndex(r=>r.clipId===l.clipId);return c>=0?s[c+1]:void 0}function Ze(s,l,c){const r=l.findIndex(o=>o.clipId===s.clipId),h=r>0?l[r-1]:void 0,f=r>=0?l[r+1]:void 0;return{left:s.timelineStartFrame-(h?x(h):0),right:(f?f.timelineStartFrame:c)-x(s)}}function pi(s,l,c){if(s.source.kind!=="timed")return{before:s.timelineStartFrame,after:Number.MAX_SAFE_INTEGER};const r=s,h=r.speed.numerator/r.speed.denominator,f=r.source.range.timeBase.numerator/r.source.range.timeBase.denominator,o=r.source.range.startTick*f,w=(r.source.range.startTick+r.source.range.durationTicks)*f,ne=l?.duration??w,U=Math.floor(o*c/h),P=Math.floor(Math.max(0,ne-w)*c/h);return r.reverse?{before:P,after:U}:{before:U,after:P}}function fi(s){return/\.(avif|bmp|gif|jpe?g|png|webp)(?:$|\?)/i.test(s)}function bi(s){const l=_t.c(5),{asset:c}=s,r=c.thumbnailUrl??(c.mediaUrl&&fi(c.mediaUrl)?c.mediaUrl:null);if(r){let f;return l[0]!==r?(f=t.jsx("img",{src:r,alt:""}),l[0]=r,l[1]=f):f=l[1],f}if(c.mediaUrl){let f;return l[2]!==c.mediaUrl?(f=t.jsx("video",{src:c.mediaUrl,muted:!0,playsInline:!0,preload:"metadata",onLoadedMetadata:vi}),l[2]=c.mediaUrl,l[3]=f):f=l[3],f}let h;return l[4]===Symbol.for("react.memo_cache_sentinel")?(h=t.jsx(ii,{size:24}),l[4]=h):h=l[4],h}function vi(s){const l=s.currentTarget;l.duration>0&&(l.currentTime=Math.min(.12,l.duration*.15))}function hi(s,l){return s.status==="ready"||s.status==="applying"||s.status==="applied"?s.timelineLimitFrame:Math.max(1,...l.clips.map(x))}function wi({sequence:s,assets:l,audioArtifactId:c,setup:r,returnFocus:h,assembly:f,rhythm:o,address:w,initialFrame:ne=0,onFrameUpdate:U,onExport:P,onPlanDraft:Ye,onApplyDraft:Je,onApplySetup:Qe,onClose:se,onCommit:et,onCreateTrack:tt,onRefreshAssets:it,onRestore:Se,onReviewSetup:ke}){const $=d.useRef(null),at=d.useEffectEvent(se),[L,re]=d.useState(r.status!=="timeline"),[nt,Ie]=d.useState(34),[le,Ce]=d.useState({mode:"beats",fallback:"off"}),[st,we]=d.useState(!1),M=d.useRef(null),Ne=d.useRef(null),Me=d.useRef(null),[F,rt]=d.useState(ne),Fe=d.useCallback(e=>{rt(e),U(e)},[U]),[u,oe]=d.useState(null),[ce,lt]=d.useState(""),[C,q]=d.useState([]),ot=f.selectedClipId,N=f.selectClip,[Ee,E]=d.useState(null),[b,g]=d.useState(null),[Re,p]=d.useState(null),[de,V]=d.useState([]),[ue,W]=d.useState([]),[me,T]=d.useState(null),[G,H]=d.useState(()=>Ut(r.status)),O=l.find(e=>e.artifactId===(o.master?.source.artifactId??c)),S=[...s.tracks].sort((e,i)=>e.ordinal-i.ordinal).find(e=>e.kind==="video")??null,y=oi(s,S?.trackId??null),a=y.find(e=>e.clipId===ot)??null,X=d.useMemo(()=>new Map(l.map(e=>[e.artifactId,e])),[l]),Z=me?X.get(me):void 0,ct=d.useMemo(()=>l.flatMap(e=>e.mediaUrl?[{artifactId:e.artifactId,mediaUrl:e.mediaUrl}]:[]),[l]),pe=d.useMemo(()=>{const e=ce.trim().toLowerCase();return l.filter(i=>(i.type==="video"||i.type==="final")&&i.status==="ready"&&i.mediaUrl&&(!e||i.label.toLowerCase().includes(e)||i.artifactId.toLowerCase().includes(e)))},[l,ce]),v=o.master?o.master.timelineStartFrame+o.master.durationFrames:hi(r,s),j=s.frameRate.numerator/s.frameRate.denominator,fe=Math.max(0,...y.map(x)),Be=Math.max(0,fe-v),be=(r.status==="ready"||r.status==="applied"||r.status==="timeline")&&S!==null&&S.enabled&&!S.locked,_=a?Ee?.clipId===a.clipId?Ee:{clipId:a.clipId,startFrame:a.timelineStartFrame,endFrame:x(a)}:null,ve=a?X.get(a.source.artifactId):void 0,Te=a?pi(a,ve,j):{before:0,after:0},Y=a?y.findIndex(e=>e.clipId===a.clipId):-1,he=a?mi(y,a)?.timelineStartFrame??v:v,Ae=a?Ze(a,y,v):{left:0,right:0},dt=Y>0,ut=Y>=0&&Y<y.length-1,mt=dt||Ae.left>0,pt=ut||Ae.right>0,ft=!!(a&&he>x(a)),De=a?Math.max(0,a.timelineStartFrame-Te.before):0,ze=a?Math.min(v,x(a)+Te.after):v,J=ci(a),bt=ie.some(e=>e.value===J)?[...ie]:[{label:ui(J),value:J},...ie],Le=li(o.mapped,F),R=o.mapped.length>0,A=o.mapped.some(e=>e.bar),vt=o.analysis?.barSource==="estimated"&&!o.rhythm.settings.correction,K=o.status==="queued"||o.status==="analyzing",xe=le.mode==="bars"&&!A?le.fallback:le.mode,B=xe==="beats"&&!R||xe==="bars"&&!A?"off":xe,_e=[{value:"off",label:"Off"},{value:"beats",label:"Beats",disabled:!R,title:R?"Snap edits to beats":"Analyze beats or set a beat grid first"},{value:"bars",label:"Bars",disabled:!R,title:A?"Snap edits to bar starts":"Set up bar starts to enable bar snapping"}];function Q(e="beats"){N(null),re(!0),H("music"),e==="beats"&&we(!!o.master),Ce({mode:e,fallback:B}),e==="bars"&&requestAnimationFrame(()=>{const i=$.current?.querySelector('input[name="beats-per-bar"]');i?.focus(),i?.scrollIntoView({block:"nearest"})})}function Ue(e){if(e==="bars"&&!A){Q(e);return}Ce({mode:e,fallback:"off"})}d.useEffect(()=>{const e=$.current;e?.showModal(),e?.querySelector(".music-video-close")?.focus();const i=n=>{if(n.isComposing||n.keyCode===229||!(n.target instanceof Element)||n.target.closest("dialog")!==e)return;if(n.key==="Escape"){n.preventDefault(),at();return}if(n.key!=="Tab"||!e)return;const m=ri(e),I=m[0],D=m[m.length-1];n.shiftKey&&document.activeElement===I?(n.preventDefault(),D?.focus()):!n.shiftKey&&document.activeElement===D&&(n.preventDefault(),I?.focus())};return document.addEventListener("keydown",i),()=>{document.removeEventListener("keydown",i),e?.close(),Pt(h)}},[h]);const k=async(e,i)=>{if(b||u)return!1;if(!S)return p("Create a main video track before editing clips"),!1;if(r.status!=="ready"&&r.status!=="applied"&&r.status!=="timeline")return p("Wait for the soundtrack duration before editing clips"),!1;g(e),p(null);try{const n=await et(i,s);return V(m=>[...m,{beforeRevision:n.beforeRevision,afterRevision:n.sequence.revision}]),W([]),E(null),!0}catch(n){return p(n instanceof Error?n.message:String(n)),!1}finally{g(null)}},ee=e=>{const i=Math.max(0,Math.min(Math.max(v,...s.clips.map(x))-1,Math.round(e)));T(null),Fe(i),M.current?.seekTo(i)},ht=e=>{T(null),N(e.clipId),s.tracks.find(i=>i.trackId===e.trackId)?.kind==="audio"&&H("music"),E({clipId:e.clipId,startFrame:e.timelineStartFrame,endFrame:x(e)}),ee(e.timelineStartFrame)},xt=e=>{T(e),N(null),q(i=>i.includes(e)?i.filter(n=>n!==e):[...i,e])},gt=async()=>{!S||C.length===0||!await k("Adding clips",{kind:"append_clips",track_id:S.trackId,artifact_ids:C,timeline_limit_frame:o.master?v:Math.max(v,fe+C.reduce((i,n)=>i+Math.ceil((X.get(n)?.duration??0)*j),0)),fit:"source",visual_fit:"fit"})||(q([]),T(null))},jt=async e=>{S&&await k("Reordering clips",{kind:"reorder_clips",track_id:S.trackId,clip_ids:e,timeline_limit_frame:v})},yt=async e=>{if(!a||!S)return;const i=y.findIndex(z=>z.clipId===a.clipId),n=i+e;if(n>=0&&n<y.length){const z=y.map(zt=>zt.clipId),[Oe]=z.splice(i,1);if(!Oe)return;z.splice(n,0,Oe),await jt(z);return}const m=Ze(a,y,v),I=Math.max(1,Math.round(j)),D=e<0?-Math.min(I,m.left):Math.min(I,m.right);D!==0&&await k("Moving clip",{kind:"move",clip_id:a.clipId,track_id:S.trackId,timeline_start_frame:a.timelineStartFrame+D})},St=async()=>{if(!a||he<=x(a))return;const e=he-a.timelineStartFrame;if(a.source.kind!=="timed"){await k("Stretching clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:a.timelineStartFrame,duration_frames:e,edge:"end",ripple:!1,timeline_limit_frame:v});return}const i=a,n=di(a,j);await k("Stretching clip",{kind:"speed",clip_id:a.clipId,numerator:n,denominator:e,reverse:i.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},te=async(e,i,n)=>{if(!(!a||n<=i)&&!(i===a.timelineStartFrame&&n===x(a))){if(B!=="off"&&(e==="start"?i=ye(i,o.mapped,B):n=ye(n,o.mapped,B)),n<=i){p("Choose distinct beat boundaries or turn snapping off");return}await k("Trimming clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:i,duration_frames:n-i,edge:e,ripple:!1,timeline_limit_frame:v})}},ge=async()=>{if(!a||F<=a.timelineStartFrame||F>=x(a)){p("Place the playhead inside the selected clip before cutting");return}const e=ye(F,o.mapped,B);if(e<=a.timelineStartFrame||e>=x(a)){p("Choose a beat inside the selected clip, or turn snapping off");return}await k("Cutting clip",{kind:"split",clip_id:a.clipId,split_frame:e}),N(null)},Pe=async()=>{a&&(await k("Deleting clip",{kind:"delete",clip_id:a.clipId,ripple:!1}),N(null))},kt=async e=>{if(!a||a.source.kind!=="timed")return;const i=ie.find(z=>z.value===e),[n,m]=e.split("/").map(Number),I=i??(n&&m?{numerator:n,denominator:m}:null);if(!I)return;const D=a;await k("Retiming clip",{kind:"speed",clip_id:a.clipId,numerator:I.numerator,denominator:I.denominator,reverse:D.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},$e=async()=>{const e=de[de.length-1];if(!(!e||b)){g("Undoing edit"),p(null);try{await Se(e.beforeRevision,s.revision),V(i=>i.slice(0,-1)),W(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},He=async()=>{const e=ue[ue.length-1];if(!(!e||b)){g("Redoing edit"),p(null);try{await Se(e.afterRevision,s.revision),W(i=>i.slice(0,-1)),V(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},It=(e,i)=>{if(e==="split"&&ge(),e==="delete"&&Pe(),e==="undo"&&$e(),e==="redo"&&He(),e==="search"&&(re(!0),H("media"),requestAnimationFrame(()=>Ne.current?.focus())),e==="zoom-in"&&$.current?.querySelector('[aria-label="Zoom timeline in"]')?.click(),e==="zoom-out"&&$.current?.querySelector('[aria-label="Zoom timeline out"]')?.click(),e==="mark-in"&&a){const n=_?.endFrame??x(a);i<n&&(E({clipId:a.clipId,startFrame:i,endFrame:n}),te("start",i,n))}if(e==="mark-out"&&a){const n=_?.startFrame??a.timelineStartFrame;i>n&&(E({clipId:a.clipId,startFrame:n,endFrame:i}),te("end",n,i))}},Ct=async()=>{if(!(r.status!=="ready"||b)){g("Applying soundtrack"),p(null);try{await Qe()}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},wt=async e=>{if(!b){g("Creating soundtrack track"),p(null);try{const i=await tt(e);e==="audio"&&await ke(i)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Nt=e=>{if(e.defaultPrevented||e.nativeEvent.isComposing||e.nativeEvent.keyCode===229||e.target.closest('input, textarea, select, [contenteditable="true"], .canonical-player'))return;if(M.current){M.current.handleKeyDown(e);return}const n=Me.current,m=e.key.toLowerCase();!n||m!==" "&&m!=="k"||(e.preventDefault(),n.paused?n.play().catch(()=>{}):n.pause())},Mt=async e=>{if(!b){g("Planning draft"),p(null),M.current?.pause();try{const i=await Ye(e,s);oe(i),T(null),ee(e.start_frame)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Ft=async()=>{if(!(!u||b||u.uncovered.length)){g("Applying draft"),p(null),M.current?.pause();try{const e=await Je(u);V(i=>[...i,{beforeRevision:e.beforeRevision,afterRevision:e.sequence.revision}]),W([]),oe(null),N(null)}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},je=!be||!!b||!!u,Et=e=>{if(e.button!==0)return;const i=e.currentTarget;i.setPointerCapture(e.pointerId);const n=I=>{Ie(Xe((window.innerHeight-I.clientY)/window.innerHeight*100))},m=()=>{i.removeEventListener("pointermove",n),i.removeEventListener("pointerup",m),i.removeEventListener("pointercancel",m)};i.addEventListener("pointermove",n),i.addEventListener("pointerup",m),i.addEventListener("pointercancel",m)},Rt=e=>{const i=e.key==="ArrowUp"?2:e.key==="ArrowDown"?-2:0;i&&(e.preventDefault(),e.stopPropagation(),Ie(n=>Xe(n+i)))},Bt=()=>{M.current?.pause(),oe(null)},Tt=C.flatMap(e=>{const i=X.get(e);return i?[i]:[]}),At=A?vt?` · Estimated ${o.analysis?.beatsPerBar}-beat bars`:"":" · Bars not set",Dt=K?"Analyzing beats…":R?`${o.mapped.length} beats${o.analysis?.lowConfidence&&!o.rhythm.settings.correction?" · Review timing":""}${At}`:o.status==="no-beats"?"Analysis complete · No reliable beats found · Set a beat grid":o.master?"Analyze the soundtrack to enable snapping":"Choose a soundtrack for snapping";return Lt.createPortal(t.jsxs("dialog",{className:"music-video-editor timeline-preview-fullscreen","aria-label":w?`Timeline preview ${w}`:"Music video editor",style:{"--music-timeline-height":`${nt}dvh`},onCancel:e=>{e.preventDefault(),se()},ref:$,tabIndex:-1,onKeyDown:Nt,children:[t.jsxs("header",{className:"music-video-editor-header",children:[t.jsx("button",{className:"music-video-close mv-icon",type:"button",onClick:se,"aria-label":w?"Close timeline preview":"Close music video editor",children:t.jsx(Gt,{size:20})}),t.jsxs("div",{className:"music-video-title",children:[t.jsxs("h1",{children:[w?t.jsxs(t.Fragment,{children:["Timeline ",t.jsx("code",{children:w})]}):O?.label??"Music video",u&&t.jsx("span",{className:"mv-draft-badge",children:"Draft preview"})]}),t.jsxs("p",{children:[s.width,"×",s.height," · ",parseFloat(j.toFixed(2))," fps · ",ae(v,j)]})]}),t.jsxs("div",{className:"music-video-header-actions",children:[t.jsxs("button",{type:"button",className:"mv-quiet mv-tools-toggle","aria-pressed":L,"aria-label":L?"Hide tools":"Show tools",onClick:()=>re(e=>!e),children:[t.jsx(Xt,{size:16})," ",t.jsx("span",{children:L?"Hide tools":"Show tools"})]}),u?t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"mv-draft-note",children:"Nothing changes until you apply."}),t.jsx("button",{type:"button",disabled:!!b,onClick:Bt,children:"Discard draft"}),t.jsxs("button",{type:"button",className:"mv-apply",disabled:!!b||u.uncovered.length>0,onClick:()=>{Ft()},children:[t.jsx(qe,{size:16})," Apply draft"]})]}):t.jsxs(t.Fragment,{children:[t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||de.length===0,onClick:()=>{$e()},children:[t.jsx(Zt,{size:16})," Undo"]}),t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||ue.length===0,onClick:()=>{He()},children:[t.jsx(Yt,{size:16})," Redo"]}),t.jsxs("button",{type:"button",className:"mv-primary",onClick:P,children:[t.jsx(Jt,{size:16})," Export"]})]})]})]}),t.jsxs("main",{className:["music-video-editor-main",L?"":"tools-hidden",a||u?"inspecting":""].filter(Boolean).join(" "),children:[t.jsxs("aside",{className:"music-video-library","aria-label":"Library",hidden:!L,children:[t.jsx("div",{className:"music-video-library-tabs",role:"tablist","aria-label":"Library views",children:ai.map(e=>t.jsx("button",{type:"button",role:"tab",id:`mv-tab-${e.value}`,"aria-controls":`mv-panel-${e.value}`,"aria-selected":G===e.value,onClick:()=>H(e.value),children:e.label},e.value))}),t.jsxs("section",{className:"music-video-source-panel",role:"tabpanel",id:"mv-panel-media","aria-labelledby":"mv-tab-media",hidden:G!=="media",children:[t.jsxs("div",{className:"mv-panel-head",children:[t.jsxs("label",{className:"music-video-search",children:[t.jsx(Qt,{size:15}),t.jsx("input",{ref:Ne,value:ce,onChange:e=>lt(e.target.value),placeholder:"Search this book","aria-label":"Search source clips"})]}),t.jsx("button",{type:"button",className:"mv-icon","aria-label":"Refresh media",title:"Refresh media",onClick:()=>{it().catch(e=>p(String(e)))},children:t.jsx(Ve,{size:15})})]}),t.jsxs("div",{className:"mv-panel-meta",children:[t.jsxs("span",{children:[C.length," of ",pe.length," selected"]}),C.length>0&&t.jsx("button",{type:"button",className:"mv-link",onClick:()=>q([]),children:"Clear"})]}),t.jsxs("div",{className:"music-video-source-list",children:[pe.map(e=>{const i=C.indexOf(e.artifactId),n=me===e.artifactId;return t.jsxs("button",{type:"button",className:[i>=0?"selected":"",n?"previewing":""].filter(Boolean).join(" "),"aria-pressed":i>=0,"aria-label":e.label,onClick:()=>xt(e.artifactId),children:[t.jsxs("span",{className:"music-video-source-thumb",children:[t.jsx(bi,{asset:e}),i>=0&&t.jsx("i",{children:i+1}),e.duration!==null&&t.jsx("small",{children:ae(Math.round(e.duration*j),j)})]}),t.jsx("span",{className:"music-video-source-name",title:e.label,children:e.label})]},e.artifactId)}),pe.length===0&&t.jsx("p",{children:"No ready video sources match this search."})]}),t.jsxs("footer",{className:"mv-panel-foot",children:[t.jsxs("button",{type:"button",className:"mv-primary music-video-add-selected",disabled:je||C.length===0,onClick:()=>{gt()},children:[t.jsx(We,{size:15})," Add ",C.length||""," to end"]}),t.jsxs("button",{type:"button",disabled:C.length===0,onClick:()=>H("autocut"),children:[t.jsx(ei,{size:15})," Auto-cut…"]})]})]}),t.jsxs("section",{className:"mv-music-panel",role:"tabpanel",id:"mv-panel-music","aria-labelledby":"mv-tab-music",hidden:G!=="music",children:[t.jsxs("div",{className:"music-video-setup-card","data-status":r.status,children:[t.jsxs("span",{className:"mv-kicker",children:[t.jsx(Ge,{size:13})," Soundtrack",O?` · ${O.label}`:""]}),r.status==="loading"&&t.jsx("p",{children:"Building the exact canonical setup plan…"}),r.status==="needs-audio-track"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{children:r.message}),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{wt("audio")},children:[t.jsx(We,{size:15})," Create soundtrack track"]})]}),(r.status==="ready"||r.status==="applying")&&t.jsxs(t.Fragment,{children:[t.jsx("strong",{children:r.summary}),t.jsxs("p",{children:[r.operationCount," atomic operations · ends at ",ae(r.timelineLimitFrame,j)]}),r.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{Ct()},children:[t.jsx(Ge,{size:15})," Apply soundtrack"]})]}),r.status==="applied"&&t.jsxs("strong",{className:"music-video-applied",children:[t.jsx(qe,{size:15})," Soundtrack applied"]}),r.status==="error"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"music-video-error",children:r.message}),t.jsxs("button",{type:"button",disabled:!!b,onClick:()=>{ke()},children:[t.jsx(Ve,{size:15})," Review again"]})]})]}),t.jsxs("div",{className:"mv-control",children:[t.jsx("span",{children:"Snap edits to"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),t.jsx("p",{className:"mv-hint",children:"Hold Alt while dragging to ignore snapping."})]}),t.jsx(Ht,{rhythm:o,sequence:s,assets:l,frame:F,correctionsOpen:st,onCorrectionsOpenChange:we})]}),t.jsx("section",{className:"mv-autocut-panel",role:"tabpanel",id:"mv-panel-autocut","aria-labelledby":"mv-tab-autocut",hidden:G!=="autocut",children:t.jsx(Ot,{sources:Tt,trackId:S?.trackId??null,startFrame:o.master?.timelineStartFrame??0,endFrame:v,fps:j,hasBars:A,busy:!!b,draft:u,onPlan:e=>{Mt(e)},onOrder:q})})]}),t.jsxs("section",{className:"music-video-preview-panel timeline-preview-body","aria-label":"Program monitor",children:[t.jsx("div",{className:"mv-monitor",children:Z?.mediaUrl?t.jsxs("div",{className:"music-video-source-preview",children:[t.jsx("video",{ref:Me,src:Z.mediaUrl,controls:!0,autoPlay:!0,muted:!0,playsInline:!0},Z.artifactId),t.jsxs("p",{children:[t.jsxs("span",{children:["Source · ",Z.label]}),t.jsx("button",{type:"button",onClick:()=>T(null),children:"Show sequence"})]})]}):t.jsx(Kt,{ref:M,sequence:u?.sequence??s,assets:ct,onFrameUpdate:Fe,initialFrame:F,presentation:"preview",allowFullscreen:!1,editingEnabled:!u,onKeyboardAction:It})}),t.jsx(qt,{frame:F,durationFrames:Math.max(v,fe),fps:j,previousBeat:Le.previous,nextBeat:Le.next,onTogglePlay:()=>{T(null),M.current?.togglePlay()},onSeek:ee})]}),t.jsxs("aside",{className:"music-video-inspector","aria-label":"Inspector",hidden:!L,children:[a&&!u&&t.jsx("button",{type:"button",className:"mv-link mv-back",onClick:()=>N(null),children:"← Back to library"}),u?t.jsxs("div",{className:"mv-draft-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Draft review"}),t.jsx("strong",{children:u.plan.summary}),t.jsxs("p",{children:[u.shots.length," shots · replaces ",u.preview.diff.removedClipIds.length," clips"]}),u.uncovered.length>0&&t.jsx("p",{className:"music-video-error",children:"Gaps remain, so the draft can't be applied. Allow repeated footage or add sources in Auto-cut."}),u.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsx("p",{className:"mv-hint",children:"The full shot list is in Auto-cut."})]}):a&&_?t.jsx(Vt,{clip:a,label:ve?.label??"Clip",thumbnailUrl:ve?.thumbnailUrl??null,index:Y+1,count:y.length,fps:j,trimStart:_.startFrame,trimEnd:_.endFrame,trimMin:De,trimMax:Math.max(_.endFrame,ze),speed:J,speedOptions:bt,retimable:a.source.kind==="timed",busy:!!b,editsDisabled:je,canMoveEarlier:mt,canMoveLater:pt,canStretch:ft,onTrim:(e,i,n)=>{E({clipId:a.clipId,startFrame:i,endFrame:n}),te(e,i,n)},onSpeed:e=>{kt(e)},onFit:e=>{k("Fitting clip",{kind:"transform",clip_id:a.clipId,fit:e})},onSplit:()=>{ge()},onStretch:()=>{St()},onMove:e=>{yt(e)},onDelete:()=>{Pe()}}):t.jsxs("div",{className:"mv-sequence-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Sequence"}),t.jsxs("dl",{children:[t.jsx("dt",{children:"Frame"}),t.jsxs("dd",{children:[s.width," × ",s.height]}),t.jsx("dt",{children:"Rate"}),t.jsxs("dd",{children:[parseFloat(j.toFixed(2))," fps"]}),t.jsx("dt",{children:"Length"}),t.jsx("dd",{children:ae(v,j)}),t.jsx("dt",{children:"Clips"}),t.jsx("dd",{children:y.length})]}),y.length>0?t.jsx("p",{children:"Select a clip on the timeline to trim, retime or delete it."}):t.jsxs("ol",{className:"mv-steps",children:[t.jsx("li",{children:"Pick footage in Media"}),t.jsx("li",{children:"Choose a soundtrack in Music"}),t.jsx("li",{children:"Auto-cut, or add clips and trim by hand"})]})]})]}),t.jsxs("section",{className:"music-video-timeline-panel","aria-label":"Music video timeline",children:[t.jsx("button",{type:"button",className:"mv-resize-handle","aria-label":"Resize timeline",title:"Drag to resize the timeline (↑/↓)",onPointerDown:Et,onKeyDown:Rt}),t.jsx(Wt,{sequence:u?.sequence??s,assets:l,assembly:f,disabled:!!b||!!u,frame:F,address:w??"",onSeek:ee,onSelectClip:ht,onExport:P,presentation:"preview",onMoveClip:be?(e,i)=>{k("Moving clip",{kind:"move",clip_id:e.clipId,track_id:e.trackId,timeline_start_frame:i})}:void 0,onRemoveClip:e=>{k("Removing clip",{kind:"remove_clip",clip_id:e.clipId,ripple:!1})},onTrimClip:be?(e,i,n,m)=>{e.clipId===a?.clipId&&(E({clipId:e.clipId,startFrame:n,endFrame:m}),te(i,n,m))}:void 0,trimBounds:a?{min:De,max:Math.max(x(a),ze)}:void 0,rhythm:{masterClipId:o.master?.clipId??null,markers:o.mapped,analysis:o.analysis,snap:B},toolbar:t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Snap"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),!o.master&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Choose soundtrack"}),o.master&&!R&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.analyze(!!o.analysis)},children:o.analysis?"Analyze again":"Analyze beats"}),K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.cancel()},children:"Cancel analysis"}),o.master&&!R&&o.analysis&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Set beat grid"}),R&&!A&&t.jsx("button",{type:"button",disabled:o.busy||K,onClick:()=>Q("bars"),children:"Set bars"}),t.jsxs("button",{type:"button",disabled:je||!a,title:"Split the selected clip at the playhead (S)",onClick:()=>{ge()},children:[t.jsx(ti,{size:14})," Split"]}),o.master&&t.jsxs("span",{className:"music-master-name",title:O?.label,children:["♪ ",O?.label??"Soundtrack"]}),t.jsx("span",{role:"status",children:Dt})]})}),Be>0&&t.jsxs("p",{children:[Be," frames beyond soundtrack"]})]})]}),t.jsxs("footer",{className:"music-video-status","aria-live":"polite",children:[t.jsx("span",{children:b??(u?"Draft ready · review it, then apply or discard":"Saved")}),(Re||o.error)&&t.jsx("strong",{role:"alert",children:Re||o.error}),t.jsx("span",{className:"mv-shortcuts",children:"Space play · J/L shuttle · ←/→ frame · I/O trim · S split · Delete · ⌘Z undo"})]})]}),document.body)}export{wi as MusicVideoEditor};