diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..55fd96ecf97261ce3ae1ad12bb792292d90cb642
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,96 @@
+*.7z filter=lfs diff=lfs merge=lfs -text
+*.arrow filter=lfs diff=lfs merge=lfs -text
+*.bin filter=lfs diff=lfs merge=lfs -text
+*.bz2 filter=lfs diff=lfs merge=lfs -text
+*.ckpt filter=lfs diff=lfs merge=lfs -text
+*.ftz filter=lfs diff=lfs merge=lfs -text
+*.gz filter=lfs diff=lfs merge=lfs -text
+*.h5 filter=lfs diff=lfs merge=lfs -text
+*.joblib filter=lfs diff=lfs merge=lfs -text
+*.lfs.* filter=lfs diff=lfs merge=lfs -text
+*.mlmodel filter=lfs diff=lfs merge=lfs -text
+*.model filter=lfs diff=lfs merge=lfs -text
+*.msgpack filter=lfs diff=lfs merge=lfs -text
+*.npy filter=lfs diff=lfs merge=lfs -text
+*.npz filter=lfs diff=lfs merge=lfs -text
+*.onnx filter=lfs diff=lfs merge=lfs -text
+*.ot filter=lfs diff=lfs merge=lfs -text
+*.parquet filter=lfs diff=lfs merge=lfs -text
+*.pb filter=lfs diff=lfs merge=lfs -text
+*.pickle filter=lfs diff=lfs merge=lfs -text
+*.pkl filter=lfs diff=lfs merge=lfs -text
+*.pt filter=lfs diff=lfs merge=lfs -text
+*.pth filter=lfs diff=lfs merge=lfs -text
+*.rar filter=lfs diff=lfs merge=lfs -text
+*.safetensors filter=lfs diff=lfs merge=lfs -text
+saved_model/**/* filter=lfs diff=lfs merge=lfs -text
+*.tar.* filter=lfs diff=lfs merge=lfs -text
+*.tar filter=lfs diff=lfs merge=lfs -text
+*.tflite filter=lfs diff=lfs merge=lfs -text
+*.tgz filter=lfs diff=lfs merge=lfs -text
+*.wasm filter=lfs diff=lfs merge=lfs -text
+*.xz filter=lfs diff=lfs merge=lfs -text
+*.zip filter=lfs diff=lfs merge=lfs -text
+*.zst filter=lfs diff=lfs merge=lfs -text
+*tfevents* filter=lfs diff=lfs merge=lfs -text
+docs/assets/research/meridian_architecture.png filter=lfs diff=lfs merge=lfs -text
+docs/assets/research/meridian_illustrated_method.png filter=lfs diff=lfs merge=lfs -text
+docs/assets/research/meridian_method.png filter=lfs diff=lfs merge=lfs -text
+docs/assets/research/meridian_nba_generation.png filter=lfs diff=lfs merge=lfs -text
+examples/media/sp_bouldering_hang.mp4 filter=lfs diff=lfs merge=lfs -text
+examples/media/sp_bouldering_reach.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_ballet_t30_female_arc/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_ballet_t30_male_lowarc/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_l150_nba3_apex_right14_175/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_l150_nba3_apex_right14_175/render.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_l150_nba3_apex_right14_175/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_material_l150_charge_event_return22/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_material_l150_charge_event_return22/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_motion_l150_moto_event_return30/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_motion_l150_moto_event_return30/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_nba3_l150_air_left14/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_nba3_l150_air_right14/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_nba3_l150_moment38_left14/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_nba3_l150_moment54_right14/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_return_l150_berry_event22/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_return_l150_berry_event22/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/nba3_teacher30/nba3_full_event.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/overnight/sources/dutch_ballet_female_2575.png filter=lfs diff=lfs merge=lfs -text
+videos-all/overnight/sources/dutch_ballet_male_1900.png filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/ballet.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/ballet_male.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/berry.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/berry.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/charge.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/charge.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/gymnast.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/moto.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/moto.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/moto_return.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/moto_return.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/nba.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/nba.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/powder.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/powder.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/robot.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v1/robot.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise_poster.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/teaser_meridian_showcase_v7.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/va_pi3_hi/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/va_pi3_hi/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/research_examples_v2/motor_compound.jpg filter=lfs diff=lfs merge=lfs -text
+videos-all/teaser_meridian_compound_motor_dust_explained_v1.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_ballet_l150_female_reverse45.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/source.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/out.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/meridian_ballet_l150_female_reverse45/out.mp4 filter=lfs diff=lfs merge=lfs -text
+assets/meridian_method.png filter=lfs diff=lfs merge=lfs -text
+videos-all/teaser_meridian_showcase_v9.mp4 filter=lfs diff=lfs merge=lfs -text
+videos-all/teaser_meridian_showcase_v12.mp4 filter=lfs diff=lfs merge=lfs -text
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..c389b45855337ccec8ddeb389f4fe902abcd0b19
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,84 @@
+MiniMax H3 COMMUNITY LICENSE AGREEMENT
+MiniMax H3 release date/License date: August 2, 2026.
+The scope of this License Agreement (this “Agreement”) is expressly limited to the “Applicable Territory” as defined below.
+By clicking to accept, or by using, reproducing, modifying, distributing, running, or displaying any portion or element of the MiniMax H3 Works (including through any Hosted Services) in any manner, you acknowledge and accept the terms of this Agreement, and this Agreement shall take immediate effect upon the occurrence of such act.
+I. Definitions
+1. “Acceptable Use Policy” means the policy published by MiniMax in Exhibit A.
+2. “Agreement” means the terms and conditions set forth herein that govern the use, reproduction, distribution, modification, running, and display of the MiniMax H3 Works or any portion or element thereof.
+3. “Applicable Territory” means worldwide, excluding the Excluded Territories.
+4. “Documentation” means the specifications, manuals, and documentation concerning MiniMax H3 that are publicly released by MiniMax.
+5. “Excluded Territories” means the European Union, the United Kingdom, the Republic of Korea and the United States of America.
+6. “MiniMax H3” means the video generation model, together with its software and algorithms, including trained model weights, parameters (including optimizer states), machine-learning model code, inference-supporting code, and other elements thereof made publicly available by Us, as released at https://huggingface.co/MiniMaxAI/MiniMax-H3.
+7. “MiniMax H3 Works” means (i) the Materials, (ii) the Model Derivatives, and (iii) all derivatives thereof.
+8. “Hosted Services” means hosted services provided via application programming interfaces (APIs), web access, or any other electronic or remote means.
+9. “Licensee,” “you,” or “your” means the natural or legal person exercising rights and/or using the MiniMax H3 Works for any purpose in any field of use under this Agreement.
+10. “Materials” means, collectively, MiniMax H3 and the Documentation (and any portion thereof), in each case as made available by MiniMax under this Agreement and proprietary to MiniMax.
+11. “Model Derivatives” means all of the following: (i) any modification of MiniMax H3 or any Model Derivative thereof; (ii) any work based on MiniMax H3 or any Model Derivative thereof; or (iii) any other machine learning model created by transferring the patterns of the weights, parameters, operational patterns, or Outputs of MiniMax H3 or any Model Derivative thereof to another model, such that the latter model exhibits behavior similar to MiniMax H3 or its Model Derivatives, including by distillation methods, methods using intermediate data representations, or methods based on training using synthetic-data Outputs generated by MiniMax H3 or its Model Derivatives. For the avoidance of doubt, Outputs are not deemed Model Derivatives.
+12. “Output” means any result of operating or otherwise using MiniMax H3 or any Model Derivatives (including through Hosted Services).
+13. “Third Party” means any natural or legal person that is not under common control with us or with you.
+14. “Including” means “including but not limited to.”
+15. “We,” “Us” or “MiniMax” means Nanonoble Pte. Ltd..
+II. Grant of Rights
+Solely within the Applicable Territory, we grant you a non-exclusive, non-transferable, royalty-free, limited license to use, reproduce, distribute, create derivative works (including Model Derivatives), and modify the Materials in accordance with the terms of this Agreement and the Acceptable Use Policy, based on the intellectual property and other rights owned by MiniMax that are embodied in or used by the Materials. You shall not violate (or encourage or permit any person to violate) any term of this Agreement or the Acceptable Use Policy.
+We will continuously evaluate the applicable laws, regulations and compliance requirements for the Excluded Territories. In the meantime, should any person in such Excluded Territories be interested in deploying our models, you are welcome to contact us about obtaining a license, which will be granted based on robust controls and guardrails for purposes of complying with the laws, regulations and compliance requirements of the Excluded Territories.
+III. Distribution and Redistribution
+Subject to and conditioned on your continuing compliance with this Agreement, including its territorial restrictions and the Acceptable Use Policy, and solely within the Applicable Territory, you may distribute or make available the MiniMax H3 Works to Third Parties within the Applicable Territory; provided, that all of the following conditions are met:
+1. You must provide a copy of this Agreement to all such Third Parties who receive the MiniMax H3 Works or use your products or services related thereto;
+2. You must cause any modified files to carry prominent notices stating that you have modified such files;
+3. You are encouraged to:
+ a. display a notice on any product or service developed using MiniMax H3 indicating that the product or service is “Powered by MiniMax H3”;
+ b. add an AI-generation identifier to files produced using generative AI models including MiniMax H3; and
+ c. publish at least one technical blog post or a public statement describing your experience using MiniMax H3 Works;
+4. All distributions to Third Parties (other than through Hosted Services) must be accompanied by a “NOTICE” text file containing the following notice:
+ “MiniMax H3 is licensed under the MiniMax H3 Community License Agreement, Copyright © 2026 MiniMax. All Rights Reserved.”
+You may add your own copyright notices on your modifications; except as provided in this Section and in Section V, however, you may not impose additional or different terms and conditions on the use, reproduction, or distribution of your modifications or of any aggregate Model Derivatives, and your use, reproduction, modification, distribution, running, and display of the work must otherwise comply with the terms and conditions of this Agreement (including the provisions concerning the Applicable Territory). If you receive the MiniMax H3 Works from a Licensee as part of an integrated end-user product, the provisions of Section III of this Agreement do not apply to you, but Section V and Exhibit A remain applicable.
+IV. Additional Commercial Terms
+1. You shall obtain a separate, prior written authorization from MiniMax by contacting api@minimax.io with the subject line “MiniMax H3 licensing - authorization request”, if your commercial products and services generate more than 20 million US dollars (or equivalent in other currencies) in yearly revenue.
+2. You shall prominently display “MiniMax H3”on the user interface of commercial product or service that uses MiniMax H3 or MiniMax H3 Works.
+V. Use Restrictions
+1. Your use of the MiniMax H3 Works must comply with applicable laws and regulations (including trade-compliance laws and regulations) and must comply with the Acceptable Use Policy for the MiniMax H3 Works, which is incorporated into this Agreement by reference.
+2. Before providing access to the MiniMax H3 Works or any product, service, or Hosted Service incorporating them, you must bind each recipient or user to enforceable terms at least as protective as the use restrictions in this Section V and Exhibit A, and you must notify each recipient or user that those restrictions apply.
+3. You may not use the MiniMax H3 Works or any of their Outputs or results to improve any other artificial intelligence model (other than MiniMax H3 or its Model Derivatives).
+4. You may not use, reproduce, modify, distribute, or display the MiniMax H3 Works or any of their Outputs or results outside the Applicable Territory. Any such use outside the Applicable Territory is not authorized by this Agreement.
+5. If you provide or make available to any Third Party a product, service, or Hosted Service that permits the generation of Outputs using MiniMax H3 or any Model Derivative, you must, before making that product or service available and throughout its operation, implement, maintain, test, and periodically review reasonable and proportionate technical and organizational safeguards designed to prevent and mitigate access, uses, and Outputs that violate this Section V or Exhibit A, including uses or Outputs that infringe, misappropriate, or otherwise violate any Third Party’s intellectual-property or other rights. You must not knowingly disable, materially weaken, or permit the circumvention of those safeguards. You must maintain a reasonably accessible mechanism for reporting suspected violations. Upon receiving a good-faith report or otherwise obtaining actual knowledge of a violation, you must promptly investigate and take reasonable steps within your control to stop or mitigate the violation, including removing or disabling access to offending content or services and suspending or terminating repeat violators where appropriate. You are responsible for implementing and enforcing these requirements with respect to your products, services, systems, users, and downstream recipients.
+VI. Intellectual Property
+1. Subject to MiniMax’s rights in the MiniMax H3 Works (and the intellectual property therein), and to your compliance with the terms and conditions of this Agreement, as between you and MiniMax, you will own the derivative works and modifications of the Materials that you have created or had created, as well as any Model Derivatives.
+2. Except for the limited license expressly granted in this paragraph, no trademark license is granted under this Agreement; with respect to MiniMax H3 Works, the Licensee may not use any name or mark owned by or associated with MiniMax or any of its affiliates, except as reasonably and customarily necessary to describe and distribute the MiniMax H3 Works. MiniMax hereby grants you a license to use the “MiniMax H3” mark (the “Mark”) within the Applicable Territory solely for the purpose of complying with Section III.3; provided, that you comply with all applicable trademark-protection laws. All goodwill arising from your use of the Mark shall inure to the benefit of MiniMax.
+3. If you bring or assert any suit or other legal proceeding (including a cross-claim or counterclaim in any action) against us or any other natural or legal person alleging that the Materials, any Output, or any portion of the foregoing infringes any intellectual property right or other right owned by you or for which you can obtain a license, all licenses granted to you under this Agreement will terminate as of the date such suit or proceeding is filed. You shall defend, indemnify, and hold us harmless against any Third-Party claim arising out of or related to the use or distribution of the MiniMax H3 Works by you or by any Third Party.
+4. MiniMax claims no rights over the Outputs you generate. You and your users are entirely responsible for the Outputs and any subsequent use thereof.
+VII. Disclaimers and Limitations of Liability
+1. We have no obligation to support, update, provide training for, or develop any further version of the MiniMax H3 Works, or to grant any license with respect thereto.
+2. UNLESS AND ONLY TO THE EXTENT REQUIRED BY APPLICABLE LAW, THE MINIMAX H3 WORKS AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED “AS IS” WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND INCLUDING ANY WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, COURSE OF DEALING, USAGE OF TRADE, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING, REPRODUCING, MODIFYING, PERFORMING, DISPLAYING OR DISTRIBUTING ANY OF THE MINIMAX H3 WORKS OR OUTPUTS AND ASSUME ANY AND ALL RISKS ASSOCIATED WITH YOUR OR A THIRD PARTY’S USE OR DISTRIBUTION OF ANY OF THE MINIMAX H3 WORKS OR OUTPUTS AND YOUR EXERCISE OF RIGHTS AND PERMISSIONS UNDER THIS AGREEMENT.
+3. TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL MINIMAX OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, FOR ANY DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, EXEMPLARY, CONSEQUENTIAL OR PUNITIVE DAMAGES, OR LOST PROFITS OF ANY KIND ARISING FROM THIS AGREEMENT OR RELATED TO ANY OF THE MINIMAX H3 WORKS OR OUTPUTS, EVEN IF MINIMAX OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING.
+VIII. Term and Termination
+1. This Agreement is effective from the moment you accept this Agreement or begin accessing the Materials, and, subject to your compliance with its terms and conditions, will remain in effect until terminated as provided herein.
+2. If you breach any term or condition of this Agreement, we have the right to terminate this Agreement. Upon termination, you must immediately cease accessing, using, and distributing the MiniMax H3 Works; delete or destroy all copies within your possession or control; and notify each downstream recipient that your authorization has ended. The obligations in the preceding sentence and Sections VI.1, VI.3, VII, and IX survive termination.
+IX. Governing Law and Jurisdiction
+1. This Agreement, and any dispute arising out of or related to this Agreement, shall be governed by the laws of the Hong Kong Special Administrative Region of the People’s Republic of China, without regard to its conflict-of-laws rules. The United Nations Convention on Contracts for the International Sale of Goods does not apply to this Agreement.
+2. Any dispute arising out of or related to this Agreement shall be subject to the exclusive jurisdiction of the courts of the Hong Kong Special Administrative Region of the People’s Republic of China with competent jurisdiction. Both MiniMax and the Licensee hereby consent to the exclusive jurisdiction of such courts for any such dispute.
+Additional Note: Please note that the encoder of MiniMax H3 uses Qwen3-VL-32B, which is licensed under Apache 2.0 License: https://github.com/QwenLM/Qwen3-VL/blob/main/LICENSE.
+
+Exhibit A — Acceptable Use Policy
+MiniMax reserves the right to update this Acceptable Use Policy from time to time.
+Last revised: August 2, 2026.
+MiniMax is committed to promoting the safe and fair use of its tools and features, including MiniMax H3. You agree not to use MiniMax H3, any Model Derivatives, or any Output in any of the following ways:
+1. Use outside the Applicable Territory;
+2. Use in any manner that violates any applicable national, federal, state, local, or international law, regulation, or other legal requirement, or that infringes, misappropriates, or otherwise violates any Third Party’s intellectual-property or other proprietary rights, including through unauthorized reproduction, distribution, public display, public performance, or creation of derivative works;
+3. Use in any manner that may harm yourself or others;
+4. Use to repurpose or distribute the Outputs of MiniMax H3 or any Model Derivatives in order to harm yourself or others;
+5. Use to circumvent or bypass any safety guardrails or safeguards we have implemented;
+6. Use in any manner that exploits or harms, or intends to exploit or harm, minors;
+7. Use to generate or disseminate verifiably false information and/or content for the purpose of harming others or influencing elections;
+8. Use to manufacture or facilitate false online engagement, including fake reviews and other means of false online engagement;
+9. Use to intentionally defame, disparage, or otherwise harass others;
+10. Use to generate and/or disseminate malware (including ransomware) or any other content intended to damage electronic systems;
+11. Use to generate or disseminate personally identifiable information for the purpose of harming others;
+12. Use to generate or disseminate information (including images, code, posts, or articles) in or to any public environment (including via bot tweets or similar means) without clearly and prominently disclosing that such information and/or content is machine-generated;
+13. Use to impersonate another person without that person’s consent, authorization, or lawful right to do so;
+14. Use to make high-risk automated decisions in critical domains that affect individual safety, rights, or well-being (such as law enforcement, immigration, healthcare or medical services, critical-infrastructure management, product-safety components, essential services, credit, employment, housing, education, social scoring, or insurance);
+15. Use in any manner that violates or disregards the social, ethical, or moral standards of other countries or regions;
+16. Use to carry out, assist, threaten, incite, plan, advocate for, or encourage violent extremism or terrorism;
+17. Use for any purpose intended to discriminate against, or harm, individuals or groups based on protected characteristics or categories, online or offline social behavior, or known or predicted personality traits;
+18. Use to intentionally exploit the vulnerabilities of specific populations based on age, social, physical, or psychological characteristics, so as to materially distort the behavior of a member of that group in a manner that causes, or is likely to cause, physical or psychological harm to that person or to others;
+19. Use for military purposes;
+20. Use to engage in any unauthorized or unlicensed professional activity, including but not limited to financial, legal, medical or healthcare, or other professional practice.
diff --git a/LICENSE-CODE b/LICENSE-CODE
new file mode 100644
index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64
--- /dev/null
+++ b/LICENSE-CODE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/MODIFICATIONS.md b/MODIFICATIONS.md
new file mode 100644
index 0000000000000000000000000000000000000000..f776656b02dfbcd855bc8a3006411452489f670c
--- /dev/null
+++ b/MODIFICATIONS.md
@@ -0,0 +1,62 @@
+# Modified files
+
+Section III.2 of the MiniMax H3 Community License Agreement requires that modified files carry a
+prominent notice saying so. This file is that notice.
+
+Everything below is derived from [`MiniMaxAI/MiniMax-H3`](https://huggingface.co/MiniMaxAI/MiniMax-H3).
+
+## `transformer/` — modified
+
+**Every weight file in `transformer/` has been modified.** It started as the base model's `transformer/`
+(the `fl2va` video transformer, 50 layers) and every parameter was updated by a full finetune on a
+re-camera objective (source clip + a point-cloud render from a second camera → that camera's clip). The
+architecture, `config.json` and tensor names are unchanged, so it is a drop-in replacement for the base
+`transformer/`; the numbers in it are not the base model's numbers.
+
+The file layout also differs: the finetune was written as one 61.7 GiB safetensors file and re-sharded
+here, because HuggingFace rejects single files above 50 GB. The tensors and their contents are unchanged
+by that re-sharding.
+
+## `lora/pytorch_lora_weights.safetensors` — new
+
+Not a MiniMax file. A rank-128 LoRA over the linear layers of `transformer/`, trained by us with DMD
+distillation. It is a delta on the finetuned transformer above, not on the base model; loading it onto
+the stock `transformer/` produces garbage. Its sampling grid is `--steps 4 --flow-shift 3`.
+
+## `assets/fixed_embed_{n}.pt`, `assets/silence_audio_{n}.pt` — new
+
+Not MiniMax files. Frozen text-conditioning tensors (one per supported output length) computed once
+with the base model's own text encoder from the prompt in `assets/prompt.txt`, so that inference never
+loads Qwen3-VL, and the audio latent of silence at each length. They are *outputs* of the base model's
+encoders in the sense of Section I.12.
+
+## `assets/prompt.txt` — new
+
+Not a MiniMax file. The prompt text the embeddings above were computed from, included so that what
+conditions every render is readable rather than opaque.
+
+## `recam/`, `inference/`, `service/` — new
+
+Not MiniMax files. Written by us against the public `diffusers` API (`recam/h3.py` calls the pipeline's
+own layout builder and scheduler; nothing in `diffusers` is patched). Licensed under Apache 2.0
+(`LICENSE-CODE`); each Python file carries an `SPDX-License-Identifier: Apache-2.0` header.
+
+## Not included: VGGT-Omega
+
+Inference depends on Meta's VGGT-Omega for geometry. It is not redistributed here (FAIR Noncommercial
+Research License, gated weights); `recam/geometry.py` imports it from a path you provide. See README.md.
+
+## `LICENSE`, `LICENSE-CODE`, `NOTICE`
+
+`LICENSE` is the MiniMax H3 Community License Agreement, included unmodified as Section III.1 requires.
+`LICENSE-CODE` is the Apache 2.0 text and covers the code directories only. `NOTICE` records the
+attribution and that the weights are not Apache 2.0.
+
+Sampling draws every noise tensor on the CPU from the seeded generator, so a `--seed` reproduces across
+GPU models. The internal tooling drew them in a different order and on the device, so a seed does not
+reproduce a take made with it.
+
+## `examples/media/` — new
+
+Two clips from Wikimedia Commons under CC0, cut to 73 frames at 1280 × 720 with the soundtrack removed.
+Provenance in `examples/CREDITS.md`. Not MiniMax material.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000000000000000000000000000000000000..82dd7ab3ef45582b4d93c1bb3d19662c32e985b7
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,22 @@
+MiniMax H3 is licensed under the MiniMax H3 Community License Agreement,
+Copyright © 2026 MiniMax. All Rights Reserved.
+
+---
+
+Viggle-Recam is a Model Derivative of MiniMax H3, as that term is defined in
+Section I.11 of the MiniMax H3 Community License Agreement. It is distributed
+under that same Agreement, a copy of which is included in this repository as
+LICENSE. See MODIFICATIONS.md for the list of files that were modified.
+
+Powered by MiniMax H3.
+
+Modifications and additions Copyright © 2026 Viggle AI.
+
+The code in recam/, inference/ and service/ is licensed under the Apache
+License 2.0 (LICENSE-CODE). The model weights are not.
+
+This repository does not contain VGGT-Omega. Inference depends on it, and it is
+distributed by Meta under the FAIR Noncommercial Research License; see README.md.
+
+The two clips in examples/media/ are Wikimedia Commons material released under
+CC0 1.0; see examples/CREDITS.md.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4184e0bba1bc53c390d0bd019309c6ae39228f4e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,259 @@
+---
+license: other
+license_name: minimax-h3-community-license
+license_link: LICENSE
+base_model: MiniMaxAI/MiniMax-H3
+pipeline_tag: video-to-video
+tags:
+ - video-to-video
+ - novel-view-synthesis
+ - camera-control
+ - re-camera
+---
+
+# Meridian: A new perspective on space and time
+
+By **Viggle AI** · built on **[MiniMax-H3](https://huggingface.co/MiniMaxAI/MiniMax-H3)** ·
+geometry by **[VGGT-Omega](https://github.com/facebookresearch/vggt-omega)**
+
+**One event. Anywhere. Anytime.**
+
+**Meridian is a geometry-guided video model for authoring new observations of existing events.**
+Revisit a recorded event from a new viewpoint. Let the action unfold, slow it down, or hold a
+moment still—all while moving the camera along a path you choose.
+You can also create a camera move from a single image.
+
+[Quickstart](#quickstart) · [Method](#method)
+
+
+
+## See it in motion
+
+The motocross example includes the original video and a diagram of the planned camera path.
+The ballet example uses a single photograph. The NBA edit labels the parts taken from the original footage.
+
+
+
+
+
+ Watch the example .
+
+ A dunk. A new look at the same play. This edit combines generated views with original footage, including the dunk's finish.
+
+
+
+ Watch the example .
+
+ Play. Hold. Resume. Pause the splash, move the camera, then let the action continue.
+
+
+
+
+
+ Watch the example .
+
+ Compose a camera path. Orbit, move sideways, and change distance—all in one continuous shot.
+
+
+
+ Watch the example .
+
+ One image. Another viewpoint. A camera move from a single ballet photograph.
+
+
+
+
+## Space and time, independently
+
+| Choose… | What you can do |
+|---|---|
+| **Where to watch from** | Orbit, move in or out, slide sideways, or move up and down. Set the viewing direction and field of view. |
+| **When to watch** | Choose a sequence, hold one frame, or slow down / speed up the input video before generation. |
+| **How the two meet** | Move around a frozen moment, follow slow-motion action, or choose a new angle for a sped-up sequence. |
+
+Bullet time is one combination—not the boundary of the model. To slow down or speed up the
+action, retime the input video first. Then design the camera path over that timeline.
+
+## Beyond the frame
+
+A camera's position shapes how an event is seen: what draws our attention, what feels close,
+and what remains outside the frame. Meridian explores keeping some of those choices open
+after capture.
+
+For filmmakers, this opens room to compose a new shot around an existing moment—not just edit
+what the camera recorded, but generate another way of observing it. In the longer term, that
+freedom could extend to viewers: choosing a perspective, following a subject, or lingering on
+a detail rather than watching only a predetermined sequence.
+
+**The event has passed. The choice of how to see it remains open.**
+
+## Method
+
+
+
+*The same moment in the input, warped reference, and output. The 3D points and cameras are schematic.*
+
+**Choose the moment. Place the camera. Render the reference. Complete the view.**
+
+1. **Build the geometry.** VGGT-Omega estimates depth and camera poses from the input video.
+ We use these estimates to turn the selected frames into colored 3D points.
+2. **Render the new view.** For each output frame, choose a moment from the input and a camera
+ viewpoint. Render the corresponding points from that view, leaving uncovered regions grey.
+3. **Generate the shot.** Meridian takes the input video and the matching rendered video as
+ references, then fills in missing regions and refines the image.
+
+**Preview before generation.** Once the 3D points are available, rendering the reference is fast.
+You can check the framing and camera motion, spot gaps in the view, and adjust the path before
+running the video model.
+
+## Model
+
+Meridian uses **MiniMax-H3's transformer and VAE, without loading a text encoder at inference**.
+The task's text embeddings are precomputed; the transformer architecture is unchanged.
+
+| Component | Role |
+|---|---|
+| `transformer/` | Meridian's finetuned MiniMax-H3 checkpoint; 61.7 GiB in bf16. |
+| `lora/` | Fast-inference adapter; 2.5 GiB. Default: `--steps 4 --flow-shift 3`, **3 forwards**. |
+| `assets/` | Precomputed text embeddings, audio-layout assets, and the readable task prompt. |
+
+**Use the adapter with Meridian's transformer, not the unmodified MiniMax-H3 checkpoint.**
+
+- **Output:** 24 fps, aspect-matched 768-class canvas; 1344 × 768 for a 16:9 input.
+- **Lengths:** 73, 90, 107, 124, 141, 158, 175, or 243 frames—approximately 3–10 seconds per take.
+- **Included tools:** inference CLI, runtime assets, sample clips, and a prototype Studio.
+
+## Install
+
+Follow the **[installation guide](docs/installation.md)** for code, checkpoint setup, dependencies,
+and the separately obtained VGGT-Omega geometry model. Inference requires Meridian's transformer
+and adapter, the MiniMax-H3 VAE, and VGGT-Omega. Checkpoint availability and paths are listed in the guide.
+
+The reference implementation runs on one high-memory CUDA GPU; memory and timings are reported below.
+It does not currently expose quantization, CPU offloading, or multi-GPU sharding.
+
+**Community: bring Meridian to smaller GPUs.** Keeping MiniMax-H3's architecture and omitting the
+text encoder provides a starting point for adapting community memory-saving techniques. We welcome
+work on quantization and CPU offloading toward consumer GPUs such as the **RTX 4090**. These are
+integration targets, not supported or validated configurations in the current scripts.
+
+Review the licenses before use: the code license does not cover the weights or remove
+VGGT-Omega's noncommercial restrictions.
+
+## Quickstart
+
+After completing installation, including the separately supplied weights, run from the Meridian
+directory. The included CC0 sample clips are already 24 fps and contain 73 frames each.
+
+```bash
+# A gentle 15° orbit over the live event.
+python inference/sample.py --video examples/media/sp_bouldering_hang.mp4 \
+ --yaw 15 --sweep --ease --out out/orbit
+
+# Play 24 frames, then hold frame 24 for 49 output frames while orbiting.
+python inference/sample.py --video examples/media/sp_bouldering_reach.mp4 \
+ --yaw 35 --freeze 24:49 --out out/bullet
+```
+
+Open `out/orbit/grid.mp4` to compare **source → geometry reference → generated take**. The take is
+`out.mp4`; `render.mp4` shows the geometric input with grey holes.
+
+For your own footage, use a continuous shot exported at **constant 24 fps**. The CLI reads frames
+by index: an ordinary take needs at least `start + frames` input frames. It does not normalize the
+frame rate or detect cuts for you.
+
+## Self-hosting the demo
+
+
+
+**Early prototype.** The Studio is a very basic, vibe-coded demo, not a production editor.
+The walkthrough shows one simple way to use it.
+
+```bash
+CARD=0 bash service/run.sh --host 127.0.0.1 --port 8412
+```
+
+Open `http://127.0.0.1:8412` once the terminal prints `ready`.
+
+Upload a clip, design a path with multiple camera keyframes, preview the geometry, then generate.
+The browser provides **real-time 3D feedback** once geometry is loaded; full-path rendering and
+final video generation are separate GPU operations, not real-time generative video.
+
+The service has no authentication. The command above binds to loopback; do not expose this
+prototype directly to the internet.
+
+## Performance
+
+Reported results on **one B200 with the service resident**, using the default adapter:
+
+| Output length | Take generation | Peak GPU memory |
+|---|---|---|
+| 73 frames | ~36 s | 88 GiB |
+| 124 frames | ~80 s | 89 GiB |
+| 243 frames | ~150 s | 113 GiB |
+
+Generation timings start with geometry prepared; upload processing and reconstruction are separate.
+A 73-frame reference warp was reported at **0.24 s**, versus approximately 36 s for generation.
+These are indicative measurements, not guarantees across GPUs, resolutions, or cache states.
+
+## Limitations
+
+Unseen surfaces are generated, not recovered.
+
+- **Geometry robustness.** Meridian generally handles imperfect geometry well, but cannot reliably
+ recover from severe errors or a badly warped reference.
+- **Large moves are less stable.** Full 360° orbits can work, but large viewpoint changes can cause
+ distortion, drift, or inconsistent details in newly visible areas.
+- **Timing and continuity.** Retiming changes which input frames are used; it does not recover
+ missing motion. Separately generated clips may not join smoothly.
+
+## Documentation and code
+
+[Inference guide](docs/inference.md) — camera recipes, source timing, CLI options, and troubleshooting.
+
+Implementation lives in `recam/`, the CLI in `inference/sample.py`, and the Studio in `service/`.
+
+## License
+
+- **Weights** (`transformer/`, `lora/`, `assets/*.pt`): the
+ [MiniMax H3 Community License Agreement](LICENSE). Meridian (released as Viggle-Recam) is a Model
+ Derivative of MiniMax-H3; `MODIFICATIONS.md` is the Section III.2 notice. Powered by MiniMax H3.
+ The Agreement licenses use
+ and distribution of the weights and their outputs in its Applicable Territory only, which excludes
+ the European Union, the United Kingdom, the Republic of Korea and the United States (Section I.3,
+ I.5, V.4); read it before you download.
+- **Code** (`recam/`, `inference/`, `service/`): [Apache 2.0](LICENSE-CODE).
+- **VGGT-Omega**: not included. FAIR Noncommercial Research License v1, obtained from Meta separately;
+ see [Install](#install).
+- **Sample clips**: Wikimedia Commons, CC0; see [`examples/CREDITS.md`](examples/CREDITS.md).
+
+## Intended use
+
+Exploring new viewpoints and timing in footage you have the rights to, for previsualisation, editing,
+and creative work. Do not use it to fabricate footage of real people or events presented as genuine,
+and label what you generate as AI-generated. If you pass the weights on or host them, the Agreement
+makes you bind your users to its
+use restrictions and tell them so (Section V.2), keep safeguards on any generation service (V.5),
+display "MiniMax H3" in a commercial product's interface (IV.2), and ask MiniMax for authorization above
+US$20M yearly revenue (IV.1).
+
+## Citation
+
+```bibtex
+@misc{viggle-meridian-2026,
+ title = {Meridian: A New Perspective on Space and Time},
+ author = {Viggle AI},
+ year = {2026},
+ url = {https://huggingface.co/Viggle/Meridian}
+}
+```
diff --git a/assets/fixed_embed_107.pt b/assets/fixed_embed_107.pt
new file mode 100644
index 0000000000000000000000000000000000000000..98ec0764650cb3faece21856e98af528fd2a00d3
--- /dev/null
+++ b/assets/fixed_embed_107.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d4718b3470b5a6c6067a0aca6f4e871b7f4a12a8bbf307e1abceb7f0af0883c7
+size 5201189
diff --git a/assets/fixed_embed_124.pt b/assets/fixed_embed_124.pt
new file mode 100644
index 0000000000000000000000000000000000000000..a28b98897d544aed5deb8d9d59f4b841c21bd035
--- /dev/null
+++ b/assets/fixed_embed_124.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:183d526456085985ba2447c8dad60e9dc14e65075e942a080a8818367e352edc
+size 5324261
diff --git a/assets/fixed_embed_141.pt b/assets/fixed_embed_141.pt
new file mode 100644
index 0000000000000000000000000000000000000000..d211b8558d625308a11ab9669baee6a01ea2f047
--- /dev/null
+++ b/assets/fixed_embed_141.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3e123721344c414a0f6dd91c5ed2daf9d324c10377099140f5486c7444dde801
+size 5324261
diff --git a/assets/fixed_embed_158.pt b/assets/fixed_embed_158.pt
new file mode 100644
index 0000000000000000000000000000000000000000..e8d125fb92aae63250b7289e751e355fb0752889
--- /dev/null
+++ b/assets/fixed_embed_158.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:599e7a4b2c1fef72c15e829675c336d18082a9d5a7d74e3d58c6c95f773aee1b
+size 5447205
diff --git a/assets/fixed_embed_175.pt b/assets/fixed_embed_175.pt
new file mode 100644
index 0000000000000000000000000000000000000000..b35101bd9dc9456d27c1bb6bb2efd35bc1d30bda
--- /dev/null
+++ b/assets/fixed_embed_175.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9091ee16cbb2ea740e2acf883d22e282d0ea6f8aca5045584d300071eec8007f
+size 5570277
diff --git a/assets/fixed_embed_243.pt b/assets/fixed_embed_243.pt
new file mode 100644
index 0000000000000000000000000000000000000000..958928e241cec131a87232fa2ce951629cfee7de
--- /dev/null
+++ b/assets/fixed_embed_243.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bb55b658f35c4ac654ba9d08b1cfeaf04295935a51d09857789f6d07b131391a
+size 5959845
diff --git a/assets/fixed_embed_73.pt b/assets/fixed_embed_73.pt
new file mode 100644
index 0000000000000000000000000000000000000000..9bc1708095984c3fe2fc99373e762cab5139c0b1
--- /dev/null
+++ b/assets/fixed_embed_73.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9b297f2d18ead294f24b4c1a4fbd116049da19b833742f6c0c59d8f85478bf47
+size 5078109
diff --git a/assets/fixed_embed_90.pt b/assets/fixed_embed_90.pt
new file mode 100644
index 0000000000000000000000000000000000000000..aed79dc1a1b43a8a2f1fe0d8c3d2664b1605e79a
--- /dev/null
+++ b/assets/fixed_embed_90.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a64703d16844bdda2724d3a262eafcfaf35522b97633a1d0743477350fd1eba3
+size 5078109
diff --git a/assets/meridian_method.png b/assets/meridian_method.png
new file mode 100644
index 0000000000000000000000000000000000000000..390a7773b52bf056ef8e8cfa33b34dd3a491a321
--- /dev/null
+++ b/assets/meridian_method.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:412c686ce8c3d12784095556c7d8d6807989ffa3a0fa83a8498dbdef973d69f3
+size 491862
diff --git a/assets/prompt.txt b/assets/prompt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3a8bcb42fc22434f410fa5a35466ca8bb231f0b7
--- /dev/null
+++ b/assets/prompt.txt
@@ -0,0 +1,16 @@
+subject_definitions:
+ is the source video for the editing task.
+ is a rough render of the same scene from the new camera: the pixels of re-projected through a point cloud, so wherever it shows content its colours, framing and layout are correct, and its flat mid-grey areas are holes where the source camera saw nothing.
+
+summary:
+[video editing + viewpoint change] The target video shows exactly the same scene as , at exactly the same moments in time, filmed by the second camera that was rendered from. Every subject, every piece of clothing, the background, the lighting and the whole performance are the ones in ; only the camera differs, so the same things are seen from a different angle and at a different distance. The target video is completed: its framing and everything it shows are kept, and its grey holes are filled with what belongs there.
+
+retention_analysis:
+ (source video editing): fully_preserved - the subjects, their faces, hair, build and clothing, the background, the props and the lighting are the same objects seen from a new viewpoint, and the motion and its timing are frame for frame the motion of . Nothing is added, removed or restyled.
+ (layout reference): fully_preserved - the camera path, the framing and the placement of everything it shows are kept exactly; its grey holes are not content and are filled in so that they agree with , and its speckles and jagged edges are cleaned up.
+
+detailed_description:
+[Shot 1] One continuous shot of the scene of , framed exactly as is, frame for frame. The subjects perform the motion of with the same timing, in the same place, under the same lighting. The camera moves exactly as the camera of does, and there is no cut.
+
+overall_soundscape:
+No music and no speech.
diff --git a/assets/silence_audio_107.pt b/assets/silence_audio_107.pt
new file mode 100644
index 0000000000000000000000000000000000000000..cc2e130341e6ba9a183cd7a682244bdc5989d8a0
--- /dev/null
+++ b/assets/silence_audio_107.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6577d82d196d13bdc38669a838c7c6c868c98489f96e58569a634143f1cc335b
+size 47279
diff --git a/assets/silence_audio_124.pt b/assets/silence_audio_124.pt
new file mode 100644
index 0000000000000000000000000000000000000000..f325d2a08c5dea31691fb0da6e3236c49dcba399
--- /dev/null
+++ b/assets/silence_audio_124.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dbc857712537d96bff394a06db33cacc240dd116ec70e514ce3846d3318e467b
+size 54703
diff --git a/assets/silence_audio_141.pt b/assets/silence_audio_141.pt
new file mode 100644
index 0000000000000000000000000000000000000000..9cfcab27f7b17836e9511b59073239aba8c46e0d
--- /dev/null
+++ b/assets/silence_audio_141.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:62321eaf60a48cb717e20a7cc0ab1dfac1b0d22f034049ebb48cb4d49aca2b05
+size 61871
diff --git a/assets/silence_audio_158.pt b/assets/silence_audio_158.pt
new file mode 100644
index 0000000000000000000000000000000000000000..6bb7be273d021e284b9fecdea2eeb7eedeca493a
--- /dev/null
+++ b/assets/silence_audio_158.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:753b60bcf9691c8ae19248c0b859694afe375d835829bd105050c5f0f47d24e9
+size 69039
diff --git a/assets/silence_audio_175.pt b/assets/silence_audio_175.pt
new file mode 100644
index 0000000000000000000000000000000000000000..3c7f90dfaa98ce5861bec9b42c38f930dd80ff01
--- /dev/null
+++ b/assets/silence_audio_175.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c15014f11f175fff5cfcf5dae7d5c8871e5259373e617ad95b029984d839c29a
+size 76463
diff --git a/assets/silence_audio_243.pt b/assets/silence_audio_243.pt
new file mode 100644
index 0000000000000000000000000000000000000000..7d7a31f546865daab6ffd82b7a25fdb35ffacbea
--- /dev/null
+++ b/assets/silence_audio_243.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bc4d558711c836f98d938bab81ae6d510d56628d5eb5d3e09ebbd3635c4666a2
+size 105391
diff --git a/assets/silence_audio_73.pt b/assets/silence_audio_73.pt
new file mode 100644
index 0000000000000000000000000000000000000000..e30241a5c1d4715a8a4db10d051c51775a683b12
--- /dev/null
+++ b/assets/silence_audio_73.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:18d9509a933724c73dc44ccd33e2a908e0b34107302657b12bf8a732901eb650
+size 32936
diff --git a/assets/silence_audio_90.pt b/assets/silence_audio_90.pt
new file mode 100644
index 0000000000000000000000000000000000000000..790e30db608b6239c336e8527826ea81c6ce1b37
--- /dev/null
+++ b/assets/silence_audio_90.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1b802d4a18b75ef64298f34d2183c00acdc6bfd50548c0eaed868305351f813b
+size 40104
diff --git a/docs/api.md b/docs/api.md
new file mode 100644
index 0000000000000000000000000000000000000000..d987898a6ad43f1f1fd8a7c90fd82be2f847ed8f
--- /dev/null
+++ b/docs/api.md
@@ -0,0 +1,168 @@
+# Local studio API
+
+[← Meridian](../README.md) · [Studio and deployment](studio.md) · [Method](method.md)
+
+The FastAPI service exposes the same preparation and rendering operations used by the studio.
+This is a development API for a trusted, single-GPU deployment—not an authenticated multi-user
+service. Requests are plain JSON except for multipart upload. All source indices refer to the
+**normalized 24 fps clip**, not the original upload's timestamps.
+
+## Request flow
+
+```text
+/upload or /sample → /prepare → /warp → inspect → /render → /job/{job} → /take/{job}/{name}
+```
+
+`/prepare` must populate the source-span cache before `/warp` or `/render`. Keep the same `clip`,
+`start`, and `span_end` across those calls. If that cache entry is evicted or the service restarts,
+prepare again. Do not change requests while assuming a previously inspected preview still applies.
+
+## Shared fields
+
+| Field | Meaning |
+|---|---|
+| `clip` | ID returned by `/upload` or `/sample`. |
+| `start` | First source frame of the prepared span, inclusive. |
+| `span_end` | Last source frame of that span, inclusive. Must satisfy `0 <= start < span_end < clip.frames`. |
+| `frames` | Output length. Use one of `73, 90, 107, 124, 141, 158, 175, 243` for generation. |
+| `pivot` | Optional `[u, v]` in normalized source-image fractions; default `[0.5, 0.5]`. Sets the depth-scale neighborhood. |
+| `pivot_frame` | Source frame at which to measure pivot depth; set it explicitly, normally to `start`. |
+| `seed` | Generation seed, default `1234`. |
+| `path` | List of at least two camera keys. |
+
+The current API's per-endpoint validation is limited; unsupported output lengths may fail only when
+loading conditioning assets. Validate requests before submitting expensive GPU work. Choose a
+continuous source span: the browser avoids detected cuts, but the API does not enforce that policy.
+
+### Camera keys
+
+| Field | Meaning |
+|---|---|
+| `pos` | `[x, y, z]` position in the coordinate frame of the source camera at `start`, in units of `zm`. |
+| `look` | Look-at point in the same frame and units. |
+| `src` | Absolute source-frame index, within the prepared span. |
+| `t` | Output-frame index. First key is `0`, last is `frames - 1`; intermediate values strictly increase. |
+| `ease` | Optional boolean, default `false`. Eases camera position/look-at motion in the segment leaving this key. |
+| `focal` | Optional positive focal multiplier, default `1`, relative to that source frame's estimated lens. |
+
+Axes are **x right, y down, z forward**. Source indices must be non-decreasing. Position and look-at
+points follow slope-limited cubic Hermite/Catmull-Rom interpolation; source indices and focal
+multipliers interpolate linearly. Source indices are rounded to integers. Orientation is derived
+from the look-at direction with zero roll. Equal adjacent `src` values create a hold.
+
+## Minimal walkthrough
+
+Start the [service](studio.md#start-the-service), then upload a continuous clip containing at least
+73 normalized frames:
+
+```bash
+curl -sS -F 'file=@clip.mp4' http://127.0.0.1:8412/upload
+```
+
+Copy the response's `clip` value into the following JSON and save it as `take.json`. This example
+slides the camera right by `0.15 zm` while looking toward a point one depth unit ahead of the initial
+camera. For subject-specific framing, use the `piv` returned by `/prepare` as your look-at reference.
+
+```json
+{
+ "clip": "CLIP_ID_FROM_UPLOAD",
+ "start": 0,
+ "span_end": 72,
+ "frames": 73,
+ "pivot": [0.5, 0.5],
+ "pivot_frame": 0,
+ "seed": 1234,
+ "path": [
+ {"pos": [0, 0, 0], "look": [0, 0, 1], "src": 0, "t": 0, "ease": true, "focal": 1},
+ {"pos": [0.15, 0, 0], "look": [0, 0, 1], "src": 72, "t": 72, "ease": false, "focal": 1}
+ ]
+}
+```
+
+Prepare the geometry, then produce a preview. `/prepare` ignores the extra path fields:
+
+```bash
+curl -sS -H 'Content-Type: application/json' --data-binary @take.json \
+ http://127.0.0.1:8412/prepare
+
+curl -sS -H 'Content-Type: application/json' --data-binary @take.json \
+ http://127.0.0.1:8412/warp
+```
+
+Open the returned `truth` and `holes` URLs relative to the service origin, and inspect `ahead`,
+`moved`, and `speed`. Generation is a separate, expensive step:
+
+```bash
+curl -sS -H 'Content-Type: application/json' --data-binary @take.json \
+ http://127.0.0.1:8412/render
+```
+
+Copy the returned job ID into the commands below. Poll until `done` is true, and check that there is
+**no `error`** before downloading; failed jobs also set `done: true`.
+
+```bash
+curl -sS http://127.0.0.1:8412/job/JOB_ID_FROM_RENDER
+curl -f -o out.mp4 http://127.0.0.1:8412/take/JOB_ID_FROM_RENDER/out.mp4
+```
+
+`/render` does not enforce the browser's clearance or camera-change gates and does not require that
+`/warp` was called first. This walkthrough includes preview inspection intentionally. A returned job
+ID means the background task was started, not that input validation or generation succeeded.
+
+## Endpoints
+
+Paths below are relative to the service origin. “Shared fields” refers to the table above; not every
+endpoint consumes every field.
+
+| Endpoint | Request | Response |
+|---|---|---|
+| `GET /` | — | Studio HTML. |
+| `GET /samples` | — | Array of available sample MP4 filenames. |
+| `POST /upload` | Multipart `file`. | `{clip, frames, w, h, name, cuts, seconds, lengths}`. |
+| `POST /sample` | `{name}` from `/samples`. | Same clip metadata as upload. |
+| `POST /prepare` | `clip, start, span_end`; optional `pivot, pivot_frame`. | `{box, canvas, cond_canvas, ms, src_poses, piv, zm}`. |
+| `POST /cloud` | Shared fields plus absolute source `frame`, optional `stride` (default `5`). | `{n, zm, pts, rgb}`; flattened triples in path coordinates. |
+| `POST /warp1` | Shared fields plus `src, pos, look`; optional `focal`. | One geometry-reference JPEG at conditioning resolution. |
+| `POST /warp` | Shared fields plus `path`; optional `lite`. | Gauges, cameras, source mapping, and preview URLs. `lite: true` omits the hole/sketch previews. |
+| `POST /render` | Shared fields plus `path`. | `{job}`; rendering continues in a background thread. |
+| `GET /job/{job}` | — | Status including `stage, pct, done, payload`; `t`, `error`, or `gauges` when available. |
+| `GET /frame/{clip}/{i}.jpg` | Source index in the URL. | JPEG of the normalized source frame. |
+| `GET /warpfile/{clip}/{name}` | Use a URL returned by `/warp`. | Preview file. |
+| `GET /take/{job}/{name}` | Completed job ID and filename. | `out.mp4`, `source.mp4`, `render.mp4`, `grid.mp4`, or `last.png`. |
+
+`lengths` in upload metadata is the studio's four-option length menu, not an exhaustive list of
+asset-supported lengths. `src_poses[i]` in `/prepare` corresponds to absolute source frame
+`start + i`; each entry includes `pos`, `look`, `roll`, and normalized lens values `k`.
+
+Job `t` is elapsed time **since submission, including queue wait**. It first appears when processing
+starts and updates at stage transitions, not continuously on polling. It is not a pure render-time
+measurement.
+
+### Warp response
+
+- **`truth`**: grey-hole reference MP4 at conditioning resolution.
+- **`holes`**: magenta-hole diagnostic MP4, unless `lite` is true.
+- **`sketch`**: output-resolution geometric rasterization, unless `lite` is true; not the final
+ conditioning-resolution reference.
+- **`canvas`, `cond_canvas`**: `[width, height]` for the target and references.
+- **`tmap`**: selected source index for every output frame.
+- **`cams`**: per-output-frame position/look-at description; `piv` and `zm` describe the pivot/scale.
+- **`speed`**: source-frame rate per key segment; zero is a hold, one preserves the input pace.
+- **`coverage`**: mean geometric coverage at the rasterization resolution, not a calibrated quality score.
+- **`ahead`, `near`, `behind`, `coll`, `moved`**: geometric diagnostics. See [Preview checks](studio.md#preview-checks).
+- **`ms`**: elapsed time for the warp endpoint, including preview encoding.
+
+`turned` and `zoomed` are computed by the browser from keys; they are not fields returned by `/warp`.
+
+## Operational boundaries
+
+One process serializes GPU work through a lock. The API has no cancellation, durable queue, session
+restoration, authentication, or automatic file retention policy. Clip and geometry caches can evict
+entries while files remain on disk. Do not assume an old ID remains usable after a restart or eviction.
+
+Assertions and runtime failures may surface as HTTP errors rather than structured validation
+responses. Render failures can arrive asynchronously through `/job/{job}`. The automatically served
+FastAPI schema does not describe these JSON payloads fully because the handlers read request bodies
+directly; use this guide alongside [`service/app.py`](../service/app.py).
+
+For service flags, cache behavior, and deployment precautions, see [Studio](studio.md#memory-and-lifecycle).
diff --git a/docs/assets/research/README.md b/docs/assets/research/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..78cc6e100ac49e6ec6d074ac5dcb314663c143b1
--- /dev/null
+++ b/docs/assets/research/README.md
@@ -0,0 +1,162 @@
+# Research figure assets
+
+[← Research article](../../research.md) · [Technical method](../../method.md)
+
+## Illustrated method
+
+The article uses one integrated illustration:
+[editable SVG](meridian_illustrated_method.svg) · [PNG](meridian_illustrated_method.png) ·
+[provenance](illustrated_method_provenance.json).
+
+- **Video strips:** actual matched source / warp / output samples from
+ `meridian_longtake_l150_nba3_apex_right14_175`. The front card is output index **95**;
+ the partially visible back cards are indices **40** and **150**, representing video rather
+ than a single-image input. Aspect ratios are preserved; the front frames are uncropped.
+- **3D illustration:** a procedural, colored basketball point cloud and camera frustums,
+ explicitly labeled **schematic**. These are not saved VGGT-Omega points, estimated poses,
+ or the measured target path from this take. No reconstruction was run to make the figure.
+- **Data flow:** VGGT-Omega estimates depth and source cameras; source RGB and depth are
+ unprojected into per-frame colored points. User-specified target cameras produce the warp.
+ The time-aligned source video bypasses geometry and joins the warp as the model's other
+ video input. Blue frustums denote estimated source cameras; gold denotes authored cameras.
+
+This depicts the released [`reconstruct`, `unproject`, and `warp`](../../../recam/geometry.py)
+pipeline, not a fused persistent world or direct point-cloud conditioning of the video model.
+The model consumes **two videos**, not the plotted points or camera icons. As in the compact
+earlier figures, noise, VAE/token packing, and the discarded audio branch are omitted.
+
+The front samples map to prepared-input frame **70**, original movie frame **85**, PTS
+**2.836167 s**. The other frame mappings and file hashes are in the provenance JSON.
+NBA source-use clearance remains pending; no public promotional permission or endorsement
+is implied. The Spring figure's CC BY license does not apply to the NBA samples.
+
+Rebuild from the repository root:
+
+```bash
+/home/chenyun/miniforge3/envs/wan_new/bin/python docs/assets/research/build_illustrated_method.py
+```
+
+This reads retained videos and writes only this illustration's SVG, PNG and provenance.
+It uses CPU decoding and vector rasterization; no Studio requests, model runs, production
+video edits, or generative image replacements. Earlier figures are retained below.
+
+## NBA method figures
+
+The previous two-figure version is retained for reference:
+
+1. **Camera poses and warp:** [editable SVG](meridian_poses.svg) · [PNG](meridian_poses.png).
+ VGGT-Omega estimates source poses and depth; colored points are reprojected with manually
+ specified target-camera poses. This is a schematic, not a measured camera-path plot.
+2. **Video + warp → output:** [editable SVG](meridian_nba_generation.svg) ·
+ [PNG](meridian_nba_generation.png). The three NBA panels are actual decoded frames from one take,
+ with no generated replacements, retouching, or cropping.
+
+[Frame provenance and media hashes](nba_method_provenance.json) ·
+[Source, warp, output, and recorded controls](../../../videos-all/longtake_edit/review.html?take=nba_apex14_lora)
+
+All three panels use output index **95** (zero-based) of
+`meridian_longtake_l150_nba3_apex_right14_175`. This is inside the requested hold: prepared-input
+frame **70**, original movie frame **85**, original PTS **2.836167 s**. The source panel comes from the
+take's time-aligned `source.mp4`, not frame 95 of the original movie. The output uses Full200 / LoRA150 /
+CLI4 / shift3 / seed1234. This single-frame illustration does not certify exact pose locking or
+continuous-motion quality.
+
+**NBA footage was supplied for local research. Public promotional permission and endorsement are
+not established. The Spring figure's CC BY license below does not apply to the NBA panels.**
+
+The SVGs are the editable sources. PNGs are direct rasterizations. For either figure, run from the
+repository root, replacing `meridian_poses` with `meridian_nba_generation` for the second figure:
+
+```bash
+ffmpeg -v error -threads 2 -i docs/assets/research/meridian_poses.svg \
+ -frames:v 1 -threads 2 -y docs/assets/research/meridian_poses.png
+```
+
+## Architecture overview
+
+[Editable, full-size SVG](meridian_architecture.svg) · [PNG](meridian_architecture.png) ·
+[Frame provenance](method_provenance.json)
+
+The previous single-diagram version separates **estimated source geometry**, **user-authored target
+cameras and time**, and **the two video-model inputs**. Its data flow was checked against the released
+code:
+
+| Diagram element | Implementation |
+|---|---|
+| VGGT-Omega depth and source-camera estimates; unprojection with source RGB | [`reconstruct`, `unproject`, `warp`](../../../recam/geometry.py) |
+| Camera position, look-at point, focal scale, and integer source-frame map | [`plan_path`](../../../recam/path.py) |
+| The same frame map selects both source images and geometry; the target camera projects the points | [`geo`](../../../service/app.py) |
+| Two VAE-encoded video references, packed as tokens; target denoising and decoding | [`pack`, `denoise`, `decode_video`](../../../recam/h3.py), [`do_render`](../../../service/app.py) |
+
+Target-camera control is explicit, but does not guarantee pixel-perfect generated frames. Studio
+orientation is derived from position and look-at with zero roll; focal scale multiplies the estimated
+source focal lengths, rather than specifying an arbitrary intrinsic matrix. Time selection repeats
+or skips supplied frames, without interpolating new motion. The diagram omits target noise, reference
+noise augmentation, and the discarded audio branch; the [technical method](../../method.md) covers
+those details.
+
+The three photographic panels reuse the **same embedded JPEGs, unchanged**, from the original figure
+below. The frame indices, source attribution, transformations, and provenance below apply to both
+figures. The schematic video-strip icon is not a data sample. The SVG is the editable source; its PNG
+is a direct rasterization, not an AI-generated or retouched image.
+
+To refresh the PNG after editing the SVG, run from the repository root:
+
+```bash
+ffmpeg -v error -threads 2 -i docs/assets/research/meridian_architecture.svg \
+ -frames:v 1 -threads 2 -y docs/assets/research/meridian_architecture.png
+```
+
+## Two controls, two references, one new shot
+
+[Full-size SVG](meridian_method.svg) · [PNG](meridian_method.png) ·
+[Machine-readable provenance](method_provenance.json)
+
+The upper diagram follows the released inference implementation, not a proposed architecture:
+
+- `recam/geometry.py`: joint source reconstruction, filtered per-frame colored points, z-buffered
+ projection and grey uncovered pixels. No fused persistent 4D scene or geometric inpainting.
+- `recam/path.py`: source-frame selection `s(t)` and target camera `C(t)`.
+- `recam/h3.py` and `service/app.py`: both video references are VAE encoded and packed as reference
+ tokens; the model denoises the target, then the VAE decodes it. Coverage is diagnostic, not a
+ separate transformer mask input. The diagram omits target noise and the discarded audio branch;
+ see the [technical method](../../method.md#4-condition-the-video-transformer) for the full layout.
+
+The lower panels are **actual decoded source, geometric-reference and generated frames** from
+`meridian_grand_l150_flowers_forward70_baseaim243`, all at output index **121** (zero-based).
+This maps to prepared-input frame 121 and original movie frame 9057 / PTS 377.382 s.
+The geometric panel is taken from the saved conditioning-resolution preview, not a cleaned-up
+render. Aspect ratios are preserved; small black margins are layout padding. This is a single-frame
+illustration, not evidence of continuous motion quality or recovered ground truth.
+
+The source/output exports are 1920 × 800; the geometric export is 960 × 416. These are this take's
+production settings, not the default quickstart buckets. The generated frame uses Full200 + LoRA150,
+CLI `--steps 4 --flow-shift 3 --seed 1234`; it is not a teacher-30 result.
+
+### Attribution and transformations
+
+*Spring* (2019), © Blender Foundation | [project](https://cloud.blender.org/spring).
+Retained source: [Spring — Blender Open Movie](https://commons.wikimedia.org/wiki/File:Spring_-_Blender_Open_Movie.webm),
+identified as [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) in the retained source records.
+
+The input was slowed by repeating source frames before inference. The geometry projection and
+generated view are transformations of that material. Figure preparation extracts one matched
+frame, downsamples source/output thumbnails, JPEG-encodes the panels and fits them without cropping.
+No generative image editing, enhancement, surface repair or color treatment is used for the figure.
+Retain the attribution and transformation notice when reusing the visual.
+
+[Original input preparation and exact map](../../../videos-all/longtake_edit/plates/flowers_linger243.json)
+· [Recorded recipe and raw audit](../../../videos-all/longtake_edit/review/meridian_grand_l150_flowers_forward70_baseaim243/audit.json)
+· [Source, projection and output in motion](../../../videos-all/longtake_edit/grand.html?take=flowers_forward70_baseaim)
+
+### Rebuild
+
+From the repository root, with FFmpeg's `librsvg` decoder available:
+
+```bash
+/home/chenyun/miniforge3/envs/wan_new/bin/python docs/assets/research/build_method_figure.py
+```
+
+This reads the retained MP4s and writes only the SVG, PNG and provenance beside this file.
+It uses CPU decoding and SVG rasterization; it does not invoke the model,
+contact the Studio service, or change production videos.
diff --git a/docs/assets/research/illustrated_method_provenance.json b/docs/assets/research/illustrated_method_provenance.json
new file mode 100644
index 0000000000000000000000000000000000000000..ac04898da6e2d4c204d2aec3fddf6ee330cd7a23
--- /dev/null
+++ b/docs/assets/research/illustrated_method_provenance.json
@@ -0,0 +1,101 @@
+{
+ "take": "videos-all/meridian_longtake_l150_nba3_apex_right14_175",
+ "media": {
+ "source": {
+ "path": "videos-all/meridian_longtake_l150_nba3_apex_right14_175/source.mp4",
+ "sha256": "642f992fdc516c57fbaeabd9c4a6aa773c76fb9f1fd342412e20baa27b3dbb46",
+ "samples": [
+ {
+ "frame": 40,
+ "jpeg_sha256": "993b86a03df949e23a31b6ba4b64c0fd896516851d633cf279b9dad8faf4c19c"
+ },
+ {
+ "frame": 95,
+ "jpeg_sha256": "638ad3ceee19eaf238979fa5deb302394c3e750cba67d989405d303f80afd522"
+ },
+ {
+ "frame": 150,
+ "jpeg_sha256": "dd976c5db5a7861dbbdf174a79e3a233e98ef67bebf4e156203a2f749049720d"
+ }
+ ]
+ },
+ "render": {
+ "path": "videos-all/meridian_longtake_l150_nba3_apex_right14_175/render.mp4",
+ "sha256": "e4f130524c2e09351203ca6dd410b3505031e72cdb4411e3d231787dba62bd23",
+ "samples": [
+ {
+ "frame": 40,
+ "jpeg_sha256": "b83be569064e26cefdf9bba2c5c89e3e63cd0c35beca4eeb57a8bda181406d2d"
+ },
+ {
+ "frame": 95,
+ "jpeg_sha256": "36347035ab0051f8a93fd1f1bb2bd31420de3a5be21b942a76f78e3742ce4171"
+ },
+ {
+ "frame": 150,
+ "jpeg_sha256": "1383ab0dd947894b3c05986e3f5b7b901061eca752f263e6e69aa8d4b4dff730"
+ }
+ ]
+ },
+ "out": {
+ "path": "videos-all/meridian_longtake_l150_nba3_apex_right14_175/out.mp4",
+ "sha256": "49d33d29dca587f252dc43171e6b98513348770332ca44a8eb3a8b46b4300fb0",
+ "samples": [
+ {
+ "frame": 40,
+ "jpeg_sha256": "8ab722c84d3f21c5984cc9f294de6a208d2fd02dfcba71851660ed125b239792"
+ },
+ {
+ "frame": 95,
+ "jpeg_sha256": "dbd0138d1f7e03a002aefcceed8e3faededaade3319bc6940b0d0fb0f13876cd"
+ },
+ {
+ "frame": 150,
+ "jpeg_sha256": "7c6ed5f9f3b2003665d4e0322c0c4fa3ab9a79edcbd627eae4879a1e222d83b3"
+ }
+ ]
+ }
+ },
+ "front_frame": 95,
+ "back_frames": [
+ 40,
+ 150
+ ],
+ "matched_frames": [
+ {
+ "output_frame": 40,
+ "input_frame": 40,
+ "original_frame": 48,
+ "original_seconds": 1.6016,
+ "held": false
+ },
+ {
+ "output_frame": 95,
+ "input_frame": 70,
+ "original_frame": 85,
+ "original_seconds": 2.8361666666666667,
+ "held": true
+ },
+ {
+ "output_frame": 150,
+ "input_frame": 99,
+ "original_frame": 120,
+ "original_seconds": 4.004,
+ "held": false
+ }
+ ],
+ "video_display": "Actual decoded frames, JPEG downsampling, fit-only; overlapping cards expose parts of back frames. The front frame is uncropped. No generative replacement, retouching or repair.",
+ "geometry_display": "Procedural illustrative point cloud, camera frustums, and path; not actual VGGT-Omega output or recorded camera poses. Fixed seed 17. No reconstruction or service call.",
+ "implementation": [
+ "recam/geometry.py: reconstruct, unproject, warp",
+ "recam/path.py: plan_path",
+ "service/app.py: geo, do_render",
+ "recam/h3.py: pack, denoise, decode_video"
+ ],
+ "scope": "Architecture illustration, not measured reconstruction quality or a globally consistent world. Source time selects supplied moments. Model completion is generated, not recovered.",
+ "credit": "User-supplied NBA footage for local research. Public promotional permission and endorsement are not established.",
+ "source_map": {
+ "path": "videos-all/longtake_edit/nba_study_data.json",
+ "sha256": "d596edd2904fc3c7d1b5d5a0248ea9da05db1a43feafb5b0224acbc8f7f2d27f"
+ }
+}
diff --git a/docs/assets/research/meridian_architecture.png b/docs/assets/research/meridian_architecture.png
new file mode 100644
index 0000000000000000000000000000000000000000..886a525aad7327b4775178326dc9e1fda3ec4e9d
--- /dev/null
+++ b/docs/assets/research/meridian_architecture.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a076fe79b85f87336cf05efaefcc1d976e752f3c8a248ffebeaf79ef174a7326
+size 532716
diff --git a/docs/assets/research/meridian_architecture.svg b/docs/assets/research/meridian_architecture.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d2a0151d755dda2aca8b480390b21c75d89f0602
--- /dev/null
+++ b/docs/assets/research/meridian_architecture.svg
@@ -0,0 +1,110 @@
+
+ Meridian: from source video to a new viewpoint
+ VGGT-Omega estimates depth and source cameras. Unprojection with source RGB creates colored 3D points. The user specifies the target camera and a source-frame map. The same map selects original images and points; the target camera projects the selected points with a z-buffer, leaving grey gaps. Two videos, the selected original frames and their target-view projections, are VAE encoded and condition finetuned MiniMax-H3, alongside a fixed task instruction. Denoising and VAE decoding produce a new-view video. Panels are actual matched source, projection and generated frames from one retained flower take, not schematic replacements. Explicit camera parameters control the projection, not every generated pixel. Target noise and the discarded audio branch are omitted.
+
+
+
+
+
+
+ MERIDIAN / ARCHITECTURE
+ Estimate the geometry. Specify the shot. Generate the view.
+
+
+
+
+
+ images I
+ points P
+
+
+ Original video
+ Input RGB frames I
+
+
+
+
+
+
+
+
+
+ VGGT-Omega
+ Depth + source-camera estimates
+
+ Unproject + source RGB
+ → Colored 3D points P
+
+
+
+ YOU SPECIFY / KEYFRAMES
+ Target camera C(t)
+ Position · look-at · focal scale
+
+ Source time s(t)
+ Choose the source-frame index
+ Advance · hold · skip recorded frames
+
+
+ Explicit pose + lens → projection
+
+
+
+ Select & retime together
+ One source-frame map s(t) for images and their 3D points
+
+ I[s(t)]
+
+ P[s(t)]
+
+
+ INPUT 1 / SOURCE VIDEO
+
+
+
+
+ Reproject points
+ Target camera C(t)
+ Z-buffer · grey uncovered pixels
+ No inpainting at this stage
+
+
+
+ INPUT 2 / PROJECTED VIDEO
+
+
+
+
+
+ Original viewpoint
+ Selected moments; unchanged appearance
+
+
+ + Fixed task instruction
+
+
+
+ Meridian video model
+ Finetuned MiniMax-H3
+
+ VAE → two reference-token blocks
+ Denoise → VAE decode
+
+
+
+ OUTPUT / NEW-VIEW VIDEO
+
+
+
+ Actual matched frames · output index 121 / 243 · forward flower take · generated with the LoRA150 student.
+ Spring (2019) © Blender Foundation · CC BY 4.0 · input retimed; projected and generated views are transformations.
+
diff --git a/docs/assets/research/meridian_illustrated_method.png b/docs/assets/research/meridian_illustrated_method.png
new file mode 100644
index 0000000000000000000000000000000000000000..390a7773b52bf056ef8e8cfa33b34dd3a491a321
--- /dev/null
+++ b/docs/assets/research/meridian_illustrated_method.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:412c686ce8c3d12784095556c7d8d6807989ffa3a0fa83a8498dbdef973d69f3
+size 491862
diff --git a/docs/assets/research/meridian_illustrated_method.svg b/docs/assets/research/meridian_illustrated_method.svg
new file mode 100644
index 0000000000000000000000000000000000000000..74771695771e8e19132bc4fbf977a38b7311fcbb
--- /dev/null
+++ b/docs/assets/research/meridian_illustrated_method.svg
@@ -0,0 +1,5763 @@
+
+Meridian: geometry guides a new observation
+Input video enters VGGT-Omega, which estimates depth and source cameras. RGB unprojection creates per-frame colored 3D points. User-specified target cameras reproject selected source geometry into a warped video. The time-aligned source video and warped video both condition Meridian, a finetuned MiniMax-H3, to generate an output video. Video samples are real matched NBA frames; the point cloud, cameras and path are illustrative, not measured reconstruction data.
+
+
+
+
+
+
+MERIDIAN / METHOD
+Geometry guides a new observation.
+
+
+
+
+
+
+
+Input video
+The recorded event
+
+
+
+
+
+
+Warp video
+Grey = unseen regions
+
+
+
+
+
+
+Output video
+A generated observation
+
+VGGT-Ω
+Depth + cameras
+Estimate
+
+
+
+Colored 3D points
+Unproject depth with source RGB
+3D schematic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Estimated source cameras
+User-specified target cameras
+
+
+
+Specify the camera path
+
+
+Reproject
+
+Meridian
+MiniMax-H3
+finetuned
+
+
+Two video inputs
+
+
+
+Source video · aligned to the same selected moments
+Real video samples. Point cloud and camera path are schematic, not measured 3D data.
+
diff --git a/docs/assets/research/meridian_method.png b/docs/assets/research/meridian_method.png
new file mode 100644
index 0000000000000000000000000000000000000000..990ad43116c115766944b1e51262f8b11f484922
--- /dev/null
+++ b/docs/assets/research/meridian_method.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:54fe11c479199b5c1849c39fec09dc307ae10ecfce86378d363eaaa63533ba49
+size 705326
diff --git a/docs/assets/research/meridian_method.svg b/docs/assets/research/meridian_method.svg
new file mode 100644
index 0000000000000000000000000000000000000000..df9ff54147919257c51baf9e94399de048b5815a
--- /dev/null
+++ b/docs/assets/research/meridian_method.svg
@@ -0,0 +1,79 @@
+
+Meridian: two controls, two references, one new shot
+A source span is jointly reconstructed with VGGT-Omega. Source time selects both the source image and per-frame geometry. The authored camera projects that geometry into a grey-hole reference. Both source and projected references are VAE encoded and condition MiniMax-H3 to generate a new shot. Below the schematic, actual matched flower frames show source, projection and generated output at index 121. Geometry is not a complete persistent 4D scene.
+
+
+
+
+
+MERIDIAN / METHOD
+Geometry directs. Generation completes.
+
+
+
+WHEN s(t) Select the source image and its geometry
+
+WHERE C(t) Choose position, viewing direction and lens
+
+
+
+Source span
+Video frames or a still
+Appearance + supplied time
+
+
+
+VGGT-Omega
+Joint span reconstruction
+Depth, confidence, cameras
+
+
+
+Project geometry
+Colored points G[s(t)] → C(t)
+Z-buffer · grey uncovered pixels
+
+view ref.
+
+
+Meridian / H3
+Two refs → VAE → tokens
++ fixed task instruction
+Denoise → VAE decode
+
+
+
+Generated shot
+New view · selected moments
+Inferred, not recovered
+
+
+I[s(t)] → selected source reference
+
+
+01 / SELECTED SOURCE
+02 / GEOMETRIC REFERENCE
+03 / GENERATED VIEW
+
+
+
+
+
+
+
+
+The event's appearance and selected moment.
+Requested view; grey marks missing coverage.
+Completion and refinement, not just hole filling.
+
+Schematic above; actual matched frames below. Output index 121 of 243 · forward flower take · LoRA150 student.
+Spring (2019) © Blender Foundation · CC BY 4.0 · input retimed; geometric projection and generated view are transformations.
+
diff --git a/docs/assets/research/meridian_nba_generation.png b/docs/assets/research/meridian_nba_generation.png
new file mode 100644
index 0000000000000000000000000000000000000000..354fa72e6beff97472283e02e453e15d995d23bd
--- /dev/null
+++ b/docs/assets/research/meridian_nba_generation.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fd01205c25ed6d5bea2419deb2394733a476ee461ba3a8936c48b5891f2c629c
+size 565115
diff --git a/docs/assets/research/meridian_nba_generation.svg b/docs/assets/research/meridian_nba_generation.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2596529a5d7a146d505430c15e22fdfa3ea262bc
--- /dev/null
+++ b/docs/assets/research/meridian_nba_generation.svg
@@ -0,0 +1,35 @@
+
+ Original video plus warped video generates a new view.
+ Two inputs, the original video at the selected source time and its warped video, feed the MiniMax-H3 video model. The output is a generated new-view video. Actual NBA source, warp and output frames come from output index 95 of the same retained take, corresponding to prepared source frame 70. These are local research previews, not evidence of exact pose locking or public-use clearance.
+
+
+
+
+
+ 02 / Original video + warped video → output
+
+ Original video
+
+
+ +
+ Warped video
+
+
+
+
+
+
+ Video model
+ MiniMax-H3
+
+
+ Generated video
+
+
+
+ NBA · matched source / warp / output frames · local research preview; public-use permission not established.
+
diff --git a/docs/assets/research/meridian_poses.png b/docs/assets/research/meridian_poses.png
new file mode 100644
index 0000000000000000000000000000000000000000..280d2510607da75d358e9e2ba308162f97c66ed2
Binary files /dev/null and b/docs/assets/research/meridian_poses.png differ
diff --git a/docs/assets/research/meridian_poses.svg b/docs/assets/research/meridian_poses.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c068cc936fcd8d0bbf040019d5271e1c3d6c9f8b
--- /dev/null
+++ b/docs/assets/research/meridian_poses.svg
@@ -0,0 +1,38 @@
+
+ Estimate source poses. Specify target poses.
+ The input video goes to VGGT-Omega. Estimated source-camera poses and depth give colored 3D points. These points are reprojected using manually specified target-camera poses to produce a warped video.
+
+
+
+
+
+
+ 01 / Camera poses → warped video
+
+
+ Manually specify
+ target camera poses
+
+
+
+ Input video
+
+
+
+ VGGT-Omega
+
+
+
+ Source poses
+ + 3D points
+
+ reproject
+
+
+ Warped video
+
diff --git a/docs/assets/research/method_provenance.json b/docs/assets/research/method_provenance.json
new file mode 100644
index 0000000000000000000000000000000000000000..48651a97c3991bef04b1301db1b8d17d896acf6d
--- /dev/null
+++ b/docs/assets/research/method_provenance.json
@@ -0,0 +1,29 @@
+{
+ "take": "videos-all/meridian_grand_l150_flowers_forward70_baseaim243",
+ "output_frame_zero_based": 121,
+ "prepared_input_frame": 121,
+ "original_movie_frame": 9057,
+ "original_movie_pts_seconds": 377.382,
+ "media": {
+ "source": {
+ "path": "videos-all/meridian_grand_l150_flowers_forward70_baseaim243/source.mp4",
+ "sha256": "0270cc8f8ce6e1ed3c0ceb9d6b5000c4ccaddda03f4f220359d32c2def7f3e2e"
+ },
+ "render": {
+ "path": "videos-all/meridian_grand_l150_flowers_forward70_baseaim243/render.mp4",
+ "sha256": "d1b1ad58b9c661cc780e43ceb4ca19b7f41640566d9fc36ab093e1fab7157c25"
+ },
+ "out": {
+ "path": "videos-all/meridian_grand_l150_flowers_forward70_baseaim243/out.mp4",
+ "sha256": "35d85aeda901c7c12e95de6ad2d33ad0946745282e2c2313d5dd21e5bd746961"
+ }
+ },
+ "display": "Exact decoded frame selection; JPEG encoding and fit-only thumbnail downsampling. No crop, repair or generated replacement images.",
+ "source_url": "https://commons.wikimedia.org/wiki/File:Spring_-_Blender_Open_Movie.webm",
+ "credit": "Spring (2019) \u00a9 Blender Foundation | cloud.blender.org/spring",
+ "license": "CC BY 4.0",
+ "license_url": "https://creativecommons.org/licenses/by/4.0/",
+ "source_time_scope": "Published animated-film timeline, not physical capture time.",
+ "recipe": "Full200 / LoRA150 / CLI4 / flow shift3 / seed1234; production output1920x800, conditioning960x416.",
+ "scope": "An explanatory diagram and a single matched frame, not a quality benchmark or a continuous-motion review."
+}
diff --git a/docs/assets/research/nba_method_provenance.json b/docs/assets/research/nba_method_provenance.json
new file mode 100644
index 0000000000000000000000000000000000000000..a9ea2e8aad91e10cb40ab0e878057fd903fae6d6
--- /dev/null
+++ b/docs/assets/research/nba_method_provenance.json
@@ -0,0 +1,41 @@
+{
+ "take": "meridian_longtake_l150_nba3_apex_right14_175",
+ "study_key": "nba_apex14_lora",
+ "output_frame_zero_based": 95,
+ "output_pts_seconds": 3.9583333333333335,
+ "prepared_input_frame": 70,
+ "original_movie_frame": 85,
+ "original_movie_pts_seconds": 2.8361666666666667,
+ "source_time_held": true,
+ "media": {
+ "source": {
+ "path": "videos-all/meridian_longtake_l150_nba3_apex_right14_175/source.mp4",
+ "sha256": "642f992fdc516c57fbaeabd9c4a6aa773c76fb9f1fd342412e20baa27b3dbb46",
+ "width": 1920,
+ "height": 1088,
+ "thumbnail_sha256": "1395f7e2ed780b6fbaaa060ac3ff7ff4b46f6765437d694757d53bb44daf4204"
+ },
+ "render": {
+ "path": "videos-all/meridian_longtake_l150_nba3_apex_right14_175/render.mp4",
+ "sha256": "e4f130524c2e09351203ca6dd410b3505031e72cdb4411e3d231787dba62bd23",
+ "width": 832,
+ "height": 480,
+ "thumbnail_sha256": "ba196eb57c5c7e5c0ae9c9ca8734c5a3c8c74bf9f986d21a59a285e898be155c"
+ },
+ "out": {
+ "path": "videos-all/meridian_longtake_l150_nba3_apex_right14_175/out.mp4",
+ "sha256": "49d33d29dca587f252dc43171e6b98513348770332ca44a8eb3a8b46b4300fb0",
+ "width": 1920,
+ "height": 1088,
+ "thumbnail_sha256": "4008729e25915ce072ab733d13a806dd85623d2f9a7537cf1f2ee82267ce56b8"
+ }
+ },
+ "source_time_map": "videos-all/longtake_edit/nba_study_data.json",
+ "audit": "videos-all/longtake_edit/review/meridian_longtake_l150_nba3_apex_right14_175/audit.json",
+ "recipe": "Full200 / LoRA150 / CLI4 / shift3 / seed 1234",
+ "credit": "NBA footage supplied for local research; public promotional permission and endorsement are not established.",
+ "license": "No public-use license established; the Spring figure CC BY license does not apply.",
+ "display": "All panels select decoded output frame 95 from the same take. FFmpeg scale=960:-2 and JPEG quality 2; aspect-ratio-preserving fit in SVG. No cropping, repair, image generation, or retouching.",
+ "extraction_filter": "select='eq(n,95)',scale=960:-2",
+ "scope": "Single matched-frame architecture example, not a continuous-motion review, exact pose-locking benchmark, or public-use clearance."
+}
diff --git a/docs/inference.md b/docs/inference.md
new file mode 100644
index 0000000000000000000000000000000000000000..fbf3fa9ea753741d3848ddfd2469a0e439d5beff
--- /dev/null
+++ b/docs/inference.md
@@ -0,0 +1,296 @@
+# Inference: camera and time
+
+[← Meridian](../README.md) · [Installation](installation.md) · [Method](../README.md#method) · [Studio demo](../README.md#self-hosting-the-demo)
+
+Run the examples from the release directory after completing installation. The CLI selects one GPU
+through `CUDA_VISIBLE_DEVICES`; it does not split a take across cards.
+
+```bash
+CUDA_VISIBLE_DEVICES=0 python inference/sample.py \
+ --video examples/media/sp_bouldering_hang.mp4 \
+ --yaw 15 --sweep --out out/orbit
+```
+
+The default is a 73-frame, 24 fps take using the distilled student: `--steps 4 --flow-shift 3`.
+Use a fresh `--out` directory for each take; filenames are fixed rather than automatically versioned.
+
+## Prepare the input
+
+Use a single continuous shot. The **CLI does not normalize frame rate or detect cuts**: it reads
+decoded frames by index and always writes at 24 fps. A 30 fps or variable-frame-rate input can
+therefore change pace and lose audio alignment unless you normalize it first.
+
+```bash
+# Preserve playback duration while exporting a constant 24 fps input.
+ffmpeg -i clip.mp4 -vf "setpts=PTS-STARTPTS,fps=24" \
+ -c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac clip_24fps.mp4
+
+# Inspect the actual decoded frame count, not only the container's FPS label.
+ffprobe -v error -select_streams v:0 -count_frames \
+ -show_entries stream=width,height,r_frame_rate,nb_read_frames \
+ -of default=noprint_wrappers=1 clip_24fps.mp4
+```
+
+For a normal take, the input must contain at least `start + frames` decoded frames. The two included
+sample clips each contain exactly **73 frames at 24 fps** and no audio. A longer take needs a longer
+input or an explicit hold; simply increasing `--frames` on those samples will not extend the action.
+
+## Camera recipes
+
+The following commands all work with the included 73-frame sample as an input, subject to the
+hardware and model setup. Motion quality still depends on reconstruction and viewpoint coverage.
+
+### Orbit with a gentle start and stop
+
+```bash
+python inference/sample.py --video examples/media/sp_bouldering_hang.mp4 \
+ --yaw 15 --sweep --ease --out out/eased_orbit
+```
+
+Positive yaw moves the camera **left** around the pivot. Without `--sweep`, the offset is applied
+throughout the clip instead of ramping from the original view. It remains an offset from each source
+camera, not necessarily a camera fixed in world space.
+
+### Push in without changing the lens
+
+```bash
+python inference/sample.py --video examples/media/sp_bouldering_hang.mp4 \
+ --dolly 0.8 --zoom 1 --sweep --ease --out out/push_in
+```
+
+**`--dolly` alone performs a dolly zoom:** it changes both the camera radius and focal length to
+approximately preserve the pivot plane's size. Add `--zoom 1` for a fixed-lens push-in, where the
+subject grows in frame. `--zoom 1.5` without translation is an optical zoom; these pure-zoom takes
+can be ignored by the model. Prefer moves with parallax.
+
+### Slide or crane while keeping the subject framed
+
+```bash
+# Move right by 0.15 pivot-depth units and aim back toward the pivot.
+python inference/sample.py --video examples/media/sp_bouldering_hang.mp4 \
+ --truck 0.15 --aim --sweep --ease --out out/slide
+
+# Raise the camera by 0.15 pivot-depth units.
+python inference/sample.py --video examples/media/sp_bouldering_hang.mp4 \
+ --boom 0.15 --aim --sweep --ease --out out/crane
+```
+
+### Choose the orbit center
+
+```bash
+python inference/sample.py --video examples/media/sp_bouldering_hang.mp4 \
+ --pivot 0.5,0.5 --pivot-lock --yaw 15 --sweep --out out/pivot_orbit
+```
+
+`--pivot fx,fy` uses fractions of the **center-cropped picture**, not the full letterbox or original
+uncropped image. Choose a point on the subject, away from image boundaries, sky, and missing depth.
+The example selects the crop center; adjust it for your footage. `--pivot` sets the depth scale;
+`--pivot-lock` additionally moves the orbit center to the picked 3D point.
+
+**Choose the point in the frame used for pivot depth.** Without `--freeze`, this is
+the first selected source frame (`--start`). With `--freeze F:N`, it is frame `F`.
+An athlete-centered point at the held apex can land on the distant audience in the
+approach frame: do not reuse it unchanged when removing the hold. The depth is a
+median over a neighborhood extending roughly 5% of the picture in each direction,
+so check that neighborhood as well as the exact pixel. `--pivot-lock` is not dynamic
+subject tracking; inspect the projected reference throughout the shot before
+treating the requested trajectory as a successful composition.
+
+## Timing
+
+All CLI source indices are **zero-based absolute frame indices** in the supplied file.
+
+### Select a passage
+
+```bash
+# On an input with at least 121 frames, use source frames 48 through 120 inclusive.
+python inference/sample.py --video clip_24fps.mp4 \
+ --start 48 --frames 73 --yaw 15 --sweep --out out/later_moment
+```
+
+`--start 48` is two seconds into a 24 fps input. It is not a seek time in seconds.
+
+### Hold a moment while moving the camera
+
+```bash
+# 24 live frames, then source frame 24 repeated for 49 output frames; no tail.
+python inference/sample.py --video examples/media/sp_bouldering_reach.mp4 \
+ --yaw 35 --freeze 24:49 --out out/bullet
+
+# Hold one instant for the entire take; the camera still sweeps through 20 degrees.
+python inference/sample.py --video examples/media/sp_bouldering_reach.mp4 \
+ --yaw 20 --freeze 24:73 --start 24 --out out/held_moment
+```
+
+For `--freeze F:N`, the output consists of:
+
+1. Source frames `start` through `F - 1`, once each.
+2. Source frame `F`, repeated `N` times.
+3. Source frames after `F`, once each, until the requested output length is reached.
+
+The tail length is `frames - N - (F - start)`. Use a positive `N`, `F >= start`, and a non-negative
+tail. The source must reach frame `F + tail`. With a hold, fewer distinct source frames can produce
+a longer output, but the repeated interval contains no new event motion.
+
+By default, the camera ramp progresses only during the held interval. Add `--sweep` to move during
+the live lead-in and tail too; `--live-speed` sets their ramp speed relative to the held interval
+(default `0.33`). It controls the **camera ramp**, not playback speed.
+
+The CLI can also decode a still image, for example
+`--video still.png --freeze 0:73 --yaw 15`. This is a camera move over a held image, not animation of
+the subject. The studio's video upload workflow does not offer this short-input path.
+
+### Slow motion and speed-ups
+
+**Set the event's pace first, then author the camera.** Export the retimed source at a constant
+24 fps and use that export as the input to either the CLI or the studio.
+
+```bash
+# 0.5x: twice the duration.
+ffmpeg -i clip.mp4 -vf "setpts=2*(PTS-STARTPTS),fps=24" -an clip_slow.mp4
+
+# 2x: half the duration.
+ffmpeg -i clip.mp4 -vf "setpts=0.5*(PTS-STARTPTS),fps=24" -an clip_fast.mp4
+
+python inference/sample.py --video clip_slow.mp4 \
+ --yaw 15 --sweep --out out/slow_orbit
+
+python inference/sample.py --video clip_fast.mp4 \
+ --yaw 15 --sweep --out out/fast_orbit
+```
+
+Changing playback metadata alone is not enough for the CLI: timing must be baked into the **decoded
+frame sequence**. `fps=24` duplicates or drops frames; it does not interpolate new motion. Slow-motion
+smoothness depends on the source frame rate and any interpolation applied before inference.
+
+Check the retimed file's frame count before rendering. In particular, acceleration shortens the input:
+the included 73-frame samples become too short for an ordinary 73-frame take at 2x. Use longer footage
+or explicitly hold a moment. The commands above omit audio; retime a soundtrack separately if needed.
+
+In the studio, one source frame per output frame preserves the export's retimed pace. Stretching keys
+across the unchanged source is a different workflow: it duplicates or skips reconstructed frames and
+can trigger a speed warning.
+
+## Output lengths and resolution
+
+| `--frames` | Duration at 24 fps |
+|---|---|
+| 73 | 3.04 s |
+| 90 | 3.75 s |
+| 107 | 4.46 s |
+| 124 | 5.17 s |
+| 141 | 5.88 s |
+| 158 | 6.58 s |
+| 175 | 7.29 s |
+| 243 | 10.13 s |
+
+These are the lengths with shipped text and audio-layout assets. Other values are not accepted by
+the CLI. This is a per-take limit, not a limit on the total duration of the input file.
+
+Output uses an aspect-matched 768-class bucket, usually about 1.03 million pixels; 16:9 maps to
+1344 × 768. Both references use the smaller 480-class bucket: 832 × 480 for a 16:9 input.
+
+## Output files
+
+| File in `--out` | Contents |
+|---|---|
+| `out.mp4` | Generated take, 24 fps, no generated audio. |
+| `render.mp4` | Geometry reference at conditioning resolution, including grey holes. |
+| `source.mp4` | Source images after the selected frame mapping and output crop. A hold is visible here too. |
+| `grid.mp4` | Source, geometry reference, and generated take side by side. |
+| `out_audio.mp4` | For non-freeze commands: source-window audio muxed onto the take, when the input has audio. A silent input remains silent. |
+| `last.png` | Final generated frame. Reusing it is possible, but does not guarantee cross-take consistency. |
+| `cams.npz` | Source/target camera matrices, intrinsics, pivot metadata, crop, canvas, FPS, and command arguments. |
+
+`cams.npz` stores `c2w_src` and `c2w_dst` as camera-to-world matrices; `intr_src` and `intr_dst` are
+in the 512-space geometry grid. The `*_px` arrays are exported for the output canvas. Translation
+units are reconstruction-relative, not meters. The archive is diagnostic metadata, not a scene model.
+
+For reproducibility, retain the input export, command, seed, checkpoint revisions, and environment.
+Do not assume the CLI and studio, or different dependency/backend versions, produce bit-identical
+results from the same seed.
+
+## CLI reference
+
+Run `python inference/sample.py --help` for the parser's complete help. The tables below group the
+options by purpose; boolean flags are off unless stated otherwise.
+
+### Input and model
+
+| Option | Default | Meaning |
+|---|---|---|
+| `--video` | Required | Input video or decodable still image. |
+| `--out` | Required | Output directory. |
+| `--start` | `0` | First source-frame index. |
+| `--frames` | `73` | Supported output length from the table above. |
+| `--seed` | `1234` | Random seed. |
+| `--ckpt` | `/transformer` | Finetuned teacher directory. |
+| `--lora` | `/lora` | Student adapter directory. |
+| `--no-lora` | Off | Disable the adapter; pair with the teacher sampling settings. |
+| `--steps` | `4` | Scheduler grid points, including the terminal point. |
+| `--flow-shift` | `3` | Video schedule shift; use `12` for the teacher. |
+| `--model-dir` | `MiniMaxAI/MiniMax-H3` | Hub repo or local directory containing `vae/`. |
+| `--vggt-repo`, `--vggt` | Environment-based | VGGT-Omega source checkout and checkpoint; see [Installation](installation.md#2-obtain-vggt-omega-separately). |
+| `--attn-backend` | `_native_cudnn` | Diffusers attention backend. Alternatives are hardware- and version-dependent. |
+
+To use the teacher:
+
+```bash
+python inference/sample.py --video examples/media/sp_bouldering_hang.mp4 \
+ --yaw 15 --sweep --no-lora --steps 50 --flow-shift 12 --out out/teacher
+```
+
+### Camera and motion
+
+| Option | Default | Meaning |
+|---|---|---|
+| `--yaw` | `0` | Orbit angle in degrees; positive moves left. |
+| `--yaw-from` | `0` | Initial yaw when ramping; the live lead-in holds this value unless also swept. |
+| `--truck` | `0` | Sideways shift in pivot-depth units; positive moves right. |
+| `--boom` | `0` | Vertical shift in pivot-depth units; positive raises the camera. |
+| `--dolly` | `1` | Orbit-radius scale; below one moves closer and, by default, widens the lens. |
+| `--zoom` | `0` | Zero means automatic dolly-linked focal scaling; a positive value specifies the final focal multiplier. |
+| `--pivot` | Unset | `fx,fy` in the crop; selects the depth-scale neighborhood. |
+| `--pivot-lock` | Off | With `--pivot`, orbit about the selected 3D point. |
+| `--aim` | Off | Reorient toward the pivot after translation. |
+| `--pivot-to` | Unset | With `--aim`, a second `fx,fy` point toward which the aim transitions. |
+| `--sweep` | Off | Ramp from the initial to the final offset over the take. |
+| `--ease` | Off | Cosine ease-in/out applied to the ramp; it does not create a ramp by itself. |
+| `--bounce` | Off | There-and-back ramp, `0 → 1 → 0`; implies a ramp even without `--sweep`. |
+| `--swing` | Off | Sine ramp, `0 → 1 → 0 → −1 → 0`; implies a ramp. |
+| `--freeze` | Unset | `F:N`: hold source frame `F` for `N` output frames. |
+| `--live-speed` | `0.33` | With `--freeze --sweep`, relative camera-ramp speed outside the hold. |
+
+Use one basic ramp shape at a time. Combining `--ease`, `--bounce`, and `--swing` composes their
+functions in code order; it does not select between independent motion presets.
+
+### Advanced and diagnostic controls
+
+| Option | Default | Meaning and caveat |
+|---|---|---|
+| `--gauge-only` | Off | Reconstruct, warp, print geometry gauges, then stop before loading H3. No normal output artifacts are written. |
+| `--follow` | Off | Replay estimated source cameras over the **first selected frame's fixed geometry and RGB**. Ignores the authored yaw/translation/lens controls; it does not retain the event's live motion. |
+| `--smooth` | `8` | With `--follow`, Gaussian smoothing sigma in frames for estimated camera poses and intrinsics. `0` disables smoothing. |
+| `--cull` | Off | Reject surfaces seen from behind according to estimated depth-map normals. This removes misleading splats; it does not reveal hidden surfaces. |
+| `--fast-back` | `1` | Above one, compress the middle half of the camera ramp. Does not improve the reconstruction of an unseen back view. |
+| `--canvas` | Automatic | Explicit `WxH`, with dimensions divisible by 32; advanced override outside the reported default benchmarks. |
+| `--full` | `0` → 1280 | Override the square letterbox side. Higher values increase point-cloud sampling and memory, not VGGT's 512-pixel input resolution. |
+
+The CLI prints `ahead`, coverage, and other geometry diagnostics but **does not reject a take using
+the studio's clearance/motion thresholds**. Inspect the diagnostics and `render.mp4`; do not treat a
+successful process exit as a quality check.
+
+## Improving a take
+
+1. **Inspect the geometry reference first.** A bent subject or unstable depth in `render.mp4` usually
+ needs a better source shot or a smaller move, not more denoising steps.
+2. **Use modest viewpoint changes.** Large orbits reveal surfaces absent from the source. A plausible
+ completion can still be wrong; roughly 40° is a reported caution point, not a universal threshold.
+3. **Check the depth scale.** If a small numerical move sends the camera through the scene, pick a
+ pivot on the subject and reduce the translation.
+4. **Add parallax to lens changes.** Use a small dolly rather than relying on a pure optical zoom.
+5. **Check timing before inference.** Stuttering from repeated input frames is not a geometry failure;
+ use higher-frame-rate footage or an interpolated export when smooth slow motion matters.
+6. **Do not cross cuts.** Split the input into continuous shots yourself when using the CLI.
+
+For dependency and memory errors, see [Setup problems](installation.md#setup-problems).
diff --git a/docs/installation.md b/docs/installation.md
new file mode 100644
index 0000000000000000000000000000000000000000..a45b710c538e05f64b4393167cce3504980f4573
--- /dev/null
+++ b/docs/installation.md
@@ -0,0 +1,189 @@
+# Installation
+
+[← Meridian](../README.md) · [Inference](inference.md) · [Studio demo](../README.md#self-hosting-the-demo)
+
+## Before downloading
+
+- **Review the [licenses and intended use](../README.md#license).** The weights are not Apache 2.0,
+ the MiniMax-H3 license has territorial restrictions, and the VGGT-Omega dependency is licensed
+ separately for noncommercial research.
+- **Use a CUDA GPU with substantial memory.** The released scripts run on one GPU and do not expose
+ CPU inference, multi-GPU sharding, quantization, or CPU-offload options. The reported resident-service
+ peak is approximately 88 GiB for 73 frames. The CLI logs approximately 82 GiB of peak PyTorch-allocated
+ memory during denoising; this does not measure the whole-process peak or driver-level GPU usage.
+ A 96 GB-class GPU is the reported configuration for takes up to 124 frames; 243-frame takes reach
+ approximately 113 GiB in the service.
+ Leave headroom for geometry caches, other processes, and differences between GB and GiB.
+- **Allow disk space beyond the weights.** The teacher and adapter total approximately 64 GiB;
+ the H3 VAE, VGGT-Omega checkpoint, package caches, uploads, and generated videos are additional.
+- **Reference environment:** Python 3.12, CUDA 12.8, PyTorch 2.9.1, and torchvision 0.24.1.
+ B200 is the reported benchmark GPU, not a claim that every CUDA GPU is validated.
+- Have **Git**, **FFmpeg**, and **FFprobe** on `PATH`. Git is needed for the pinned Diffusers install;
+ the Python packages do not install the FFmpeg command-line executable.
+
+## 1. Create an environment and download the code
+
+Run these commands in a shell with Python 3.12 available. `python` below always means the Python in
+the activated environment. Sign in if repository access requires it. The command fetches code,
+runtime assets, guides, and sample clips, not the optional showcase videos or model weights.
+
+```bash
+python3.12 -m venv .venv-meridian
+source .venv-meridian/bin/activate
+python -m pip install --upgrade pip
+python -m pip install huggingface_hub
+
+hf auth login
+hf download Viggle/Meridian --local-dir Meridian \
+ --include "README.md" "LICENSE*" "NOTICE" "MODIFICATIONS.md" "requirements.txt" \
+ "recam/*" "inference/*" "service/*" "assets/*" "examples/*" \
+ "docs/installation.md" "docs/inference.md"
+cd Meridian
+python -m pip install -r requirements.txt
+python -m pip install peft==0.18.0
+
+# These must work before loading any model weights or starting the GPU service.
+python inference/sample.py --help
+python service/app.py --help
+```
+
+The PEFT package is needed by the student adapter loader and is not currently listed in
+`requirements.txt`; install it explicitly. Use a dedicated environment rather than upgrading a
+shared inference environment in place.
+
+Keep the Diffusers commit pinned by `requirements.txt` (`d6726f3`). The scripts use MiniMax-H3 classes
+and modular-pipeline helpers that may not exist in another build, even if its version string includes
+`dev`. Do not replace that dependency with an arbitrary PyPI release.
+
+### Supply the teacher and LoRA weights
+
+**Checkpoint availability:** `transformer/` and `lora/` are not hosted in this repository yet;
+a verified download source is pending. Supply the checkpoints separately using the layout below.
+Without them, the help checks can pass, but generation and Studio startup cannot run.
+
+If you already have the Meridian checkpoints, place the complete Diffusers transformer directory
+(including its configuration, weight shards, and any index file) and the student adapter alongside
+the code:
+
+```text
+Meridian/
+ inference/sample.py
+ assets/
+ transformer/
+ config.json
+ ... checkpoint files ...
+ lora/
+ pytorch_lora_weights.safetensors
+```
+
+Alternatively, add `--ckpt /absolute/path/to/transformer --lora /absolute/path/to/lora` to the CLI
+or Studio command. Use Meridian's finetuned teacher, not the unmodified MiniMax-H3 transformer.
+
+## 2. Obtain VGGT-Omega separately
+
+VGGT-Omega code and weights are **not redistributed here**. Request access to
+[facebook/VGGT-Omega](https://huggingface.co/facebook/VGGT-Omega), read its license, and authenticate
+with a Hugging Face account that has been granted access.
+
+```bash
+# Run from the Meridian release directory; the checkout is placed beside it.
+git clone https://github.com/facebookresearch/vggt-omega ../vggt-omega
+export VGGT_OMEGA_DIR="$(cd ../vggt-omega && pwd)"
+
+hf auth login
+hf download facebook/VGGT-Omega vggt_omega_1b_512.pt \
+ --local-dir "$VGGT_OMEGA_DIR/checkpoints"
+```
+
+Follow the VGGT-Omega checkout's own dependency instructions if additional packages are needed.
+Its source directory is imported directly; this release does not install it as a Python package.
+
+By default, Meridian looks for
+`$VGGT_OMEGA_DIR/checkpoints/vggt_omega_1b_512.pt`. If you already store the weight file elsewhere:
+
+```bash
+export VGGT_OMEGA_CKPT=/absolute/path/to/vggt_omega_1b_512.pt
+```
+
+Keep these exports in the shell that starts inference. The CLI and service also accept
+`--vggt-repo /absolute/path/to/vggt-omega` and `--vggt /absolute/path/to/the/checkpoint.pt`.
+
+Meta's FAIR Noncommercial Research License v1 restricts commercial use of the research materials
+and their outputs or results. Here those results include the geometry used to make the reference
+render. The Apache license on Meridian's code does not remove that restriction. Commercial use
+requires an appropriately licensed geometry solution or permission from Meta; swapping the
+geometry front end is not a built-in CLI option and requires integration work.
+
+## 3. Provide the MiniMax-H3 VAE
+
+By default, inference loads `vae/` from
+[`MiniMaxAI/MiniMax-H3`](https://huggingface.co/MiniMaxAI/MiniMax-H3). It does **not** need the base
+transformer or the text encoder. To download only the VAE for local use:
+
+```bash
+hf download MiniMaxAI/MiniMax-H3 --include "vae/*" --local-dir ../MiniMax-H3
+```
+
+Then add `--model-dir ../MiniMax-H3` to your CLI or service command. This path is the directory
+**containing** `vae/`, not `vae/` itself. Without the flag, the default Hub identifier is used and
+the VAE is loaded through the Hugging Face cache.
+
+Do not put Meridian's LoRA on the base MiniMax-H3 transformer: it was distilled on Meridian's
+finetuned teacher.
+
+## 4. Check the setup
+
+These checks import the required components without loading their weights or starting inference:
+
+```bash
+ffmpeg -version
+ffprobe -version
+python -m pip check
+python -c "import torch; print('torch:', torch.__version__, 'CUDA:', torch.version.cuda, 'available:', torch.cuda.is_available())"
+python -c "import peft; from diffusers import AutoencoderKLMiniMaxH3, MiniMaxH3Transformer3DModel, MiniMaxH3Scheduler; from recam.h3 import pack; print('H3 and PEFT imports OK')"
+python -c "import os, sys; sys.path.insert(0, os.environ['VGGT_OMEGA_DIR']); from vggt_omega.models import VGGTOmega; print('VGGT-Omega import OK')"
+```
+
+For a geometry-only check on the selected GPU:
+
+```bash
+CUDA_VISIBLE_DEVICES=0 python inference/sample.py \
+ --video examples/media/sp_bouldering_hang.mp4 \
+ --yaw 15 --sweep --gauge-only --out out/check
+```
+
+This loads VGGT-Omega and prints geometry diagnostics. It does not load the VAE or transformer, and
+does not write the normal output videos. It is not a full inference or model-memory test.
+
+Next: run the [first take](../README.md#quickstart), learn the [camera controls](inference.md), or
+start the [Studio demo](../README.md#self-hosting-the-demo).
+
+## Setup problems
+
+| Symptom | Check |
+|---|---|
+| `hf` or `ffmpeg` not found | Activate the environment for `hf`; install the system FFmpeg tools separately and check `PATH`. |
+| Hub access denied | Confirm the account has accepted the model's terms and received access; authenticate with that account. A token alone does not grant gated access. |
+| `No module named vggt_omega` | `VGGT_OMEGA_DIR` must contain the `vggt_omega/` package. Export it in the same shell that starts the process. |
+| `VGGT-Omega not found` | Check both the source checkout and checkpoint path; `VGGT_OMEGA_CKPT` must name the `.pt` file. |
+| Cannot import a MiniMax-H3 class or layout helper | Reinstall the pinned requirements in the active environment; inspect `python -c "import diffusers; print(diffusers.__file__)"` for a conflicting checkout. |
+| Missing PEFT or adapter-loading error | Install PEFT, use the finetuned teacher, and confirm the adapter filename and `--lora` directory. |
+| CUDA or attention-backend failure | Check the PyTorch/CUDA/driver combination against the reference environment. The service selects `_native_cudnn`; other hardware/backend combinations are not validated here. |
+| Out of memory | Start with 73 output frames, a short source span, and no other GPU workload. The scripts do not automatically offload to CPU. The Studio keeps its models and recent geometry caches resident. |
+
+## Lower-memory community work
+
+Meridian retains MiniMax-H3's transformer architecture and uses precomputed text embeddings, so
+inference does not load the text encoder. This is a starting point for adapting community memory-saving
+techniques—not evidence that the remaining transformer, activations, VAE, and geometry fit a smaller GPU.
+
+We welcome work on quantization and CPU offloading toward consumer GPUs such as the RTX 4090.
+Diffusers documents [quantization](https://huggingface.co/docs/diffusers/main/en/quantization/overview)
+and [memory reduction and offloading](https://huggingface.co/docs/diffusers/main/en/optimization/memory).
+These are general integration references, not a tested Meridian recipe or a reason to replace the
+pinned Diffusers build indiscriminately.
+
+The current CLI and service move their models onto one CUDA device; neither exposes those optimizations.
+A contribution needs to integrate them into the custom inference path and validate adapter loading,
+reference conditioning, image quality, peak GPU/host memory, and end-to-end latency. There is no
+verified RTX 4090 configuration or performance claim for this release.
diff --git a/docs/method.md b/docs/method.md
new file mode 100644
index 0000000000000000000000000000000000000000..1f9318af664c18798c4566f28d9d8482f25fa4c0
--- /dev/null
+++ b/docs/method.md
@@ -0,0 +1,169 @@
+# Method
+
+[← Meridian](../README.md) · [Inference](inference.md) · [Studio](studio.md)
+
+Meridian synthesizes a new observation of an existing event. It separates **which source moment is
+shown** from **which camera observes it**, then uses geometry to make that choice visible to a video
+model. The geometry supplies a spatial constraint; the model supplies the appearance of the completed
+shot, including regions the source camera did not see.
+
+This is geometry-guided video re-camera, not a persistent 4D reconstruction or an action-conditioned
+simulator. A new view is a generated interpretation of the recorded event, not evidence of what an
+unobserved camera would actually have captured.
+
+[](assets/research/meridian_method.svg)
+
+**Overview.** Source time selects both appearance and geometry; the authored camera makes a
+projected reference. Both references condition the video model. Real example: *Spring* (2019),
+© Blender Foundation, CC BY 4.0; input retimed, view projected and generated.
+[Full figure, attribution and provenance](assets/research/README.md).
+
+## 1. Choose a source timeline
+
+For each output frame `t`, a source-frame map `s(t)` selects the image and geometry to use:
+
+| Timeline | Source-frame selection |
+|---|---|
+| Preserve the input's pace | Advance one source frame per output frame. |
+| Hold a moment | Repeat one source frame while the target camera can keep moving. |
+| Slow motion or accelerated action | Retime the input to a constant 24 fps **before** reconstruction, then advance through that export normally. |
+
+Both video references follow the same selected timeline. Meridian is not asked to invent a different
+action speed from an unchanged reference. See [Timing](inference.md#timing) for frame-index semantics,
+freeze windows, and FFmpeg recipes.
+
+The CLI constructs `s(t)` from `--start`, `--frames`, and optionally `--freeze`. The studio constructs it
+from keyframes: source indices interpolate linearly and are rounded to integers. Studio source keys
+must be non-decreasing; easing affects the camera path, not the source-frame mapping.
+
+## 2. Reconstruct the source span
+
+The input is resized and letterboxed into a 1280 × 1280 square, then downsampled to 512 × 512 for
+VGGT-Omega. **One model call processes the selected source span jointly**, returning per-frame depth,
+confidence, camera extrinsics, and intrinsics. Per-frame outputs do not mean independent single-frame
+inference. Changing the reconstruction span can change estimates for frames shared by both spans.
+
+Before unprojection, the implementation removes:
+
+- Non-finite depth or confidence, and confidence values at or below `1e-5`.
+- Depth discontinuities whose 3 × 3 local range exceeds 30% of the depth magnitude.
+- The lowest-confidence 2% of the remaining candidates in each frame.
+
+Depth and validity are upsampled to the letterboxed input resolution. A pixel is retained only when
+the interpolated validity exceeds `0.999`, limiting points introduced across rejected boundaries.
+Source RGB supplies the point colors. There is no fused mesh, persistent scene optimization, or
+cross-frame point-cloud accumulation in this stage.
+
+### Coordinates and scale
+
+Geometry has a reconstruction-relative scale, not calibrated meters. Camera translations use `zm`,
+a median scene depth. Choosing a distant background as the depth reference makes the same numerical
+move much larger than choosing the subject.
+
+- **CLI:** a camera offset is applied in each selected source camera's local coordinates:
+ `C_target(t) = C_source(s(t)) @ delta(t)`. By default, `zm` comes from valid depths in the first
+ selected frame; for `--freeze`, it comes from the held frame. `--pivot fx,fy` restricts the depth
+ measurement to a neighborhood of a pixel in the **cropped image**. `--pivot-lock` also places the
+ orbit center at the corresponding 3D point.
+- **Studio:** all keys share the coordinate frame of the source camera at `start`: **x right,
+ y down, z forward**. Positions and look-at points are expressed in units of `zm`. The API measures
+ `zm` around a chosen pixel at `pivot_frame`, falling back to valid picture depths when too few
+ local points remain. The current page uses the picture center at `start` as this scale reference;
+ a key's **aims at** control changes its look-at point, not the scale reference.
+
+The CLI's source-relative trajectory and the studio's shared-frame trajectory are different ways of
+authoring a camera. Similar-looking controls need not produce identical paths on a moving-camera clip.
+
+## 3. Render a geometric reference
+
+At each output time, the selected source frame's colored point cloud is projected through the target
+camera and its lens. A z-buffer resolves visibility; each point splats onto a 3 × 3 pixel neighborhood.
+Uncovered pixels are filled with RGB `(128, 128, 128)`.
+
+The current implementation rasterizes at the **output canvas**, then downsamples the result to the
+**480-class conditioning canvas**. There is no geometric inpainting before generation. Coverage is
+computed for diagnostics, but **no coverage mask is fed to the transformer**.
+
+The studio's *what the model sees* preview and the saved `render.mp4` show this downsampled reference.
+They are encoded video previews, not lossless copies of the in-memory conditioning pixels. The
+magenta-hole view is a diagnostic visualization only; the model receives the grey-hole version.
+
+## 4. Condition the video transformer
+
+MiniMax-H3's VAE encodes two references:
+
+1. **`` — source:** the selected source images, at the 480 class.
+2. **`` — geometry:** the rendered target view, at the same conditioning class.
+
+The target is generated at the 768 class. Here “class” means an aspect-ratio bucket, not a fixed
+width or height. For a 16:9 input, the reference canvas is 832 × 480 and the output is 1344 × 768;
+square inputs use 640 × 640 and 1024 × 1024 respectively. The nearest bucket is chosen by log aspect
+ratio, with a centered crop inside the letterbox.
+
+```text
+source span ──► joint VGGT-Omega reconstruction ──► per-frame geometry
+ │ │
+ │ source-frame map + camera path│
+ │ ▼
+ │ z-buffered point splat
+ │ │
+ ▼ ▼
+source reference, 480 class view reference, 480 class
+ └────────────────────────┬──────────────────────────┘
+ ▼
+ VAE → packed reference tokens + fixed text
+ ▼
+ finetuned H3 + distilled LoRA → VAE decode
+ ▼
+ new shot, 768 class, 24 fps
+```
+
+**The references are concatenated as tokens, not added as channels.** `recam/h3.py` uses Diffusers'
+`MiniMaxH3Ref2VAPrepareLayoutStep.build_ref2va_packed_sequence` to create the reference layout,
+position IDs, and modality tags. The transformer architecture is unchanged.
+
+Reference video rows receive the upstream conditioning-noise convention
+`0.999 × latent + 0.001 × noise` and stay fixed during denoising. Target video rows begin as random
+noise. The source is also VAE-encoded at target resolution to establish the target latent shape;
+its values are **not** used to initialize the target rows.
+
+### Fixed text and the audio branch
+
+[`assets/prompt.txt`](../assets/prompt.txt) describes the two-reference editing task: retain the source
+event and complete the geometry reference's grey holes. Its embeddings are precomputed for each
+supported output length, so inference does not load Qwen3-VL. Editing the text file alone does not
+change inference; the shipped embeddings are what the model reads. An embedding-generation script
+is not included in this release.
+
+The packed layout retains H3's audio branch. Cached silence latents supply its shape and length;
+the current code initializes audio rows with noise, denoises them, and discards the result. Meridian
+does not generate or preserve a soundtrack through that branch. The CLI's optional audio file is
+instead made by muxing the source soundtrack after video generation.
+
+## 5. Sample the new shot
+
+| Mode | CLI settings | Transformer evaluations |
+|---|---|---|
+| Fast adapter, default | `--steps 4 --flow-shift 3` with the LoRA loaded | 3 |
+| Teacher | `--no-lora --steps 50 --flow-shift 12` | 49 |
+
+The H3 scheduler counts the terminal zero-noise point in `--steps`; that endpoint does not require
+another model evaluation. The adapter must be loaded on Meridian's finetuned transformer, not the
+unmodified MiniMax-H3 checkpoint. Forward counts do not equal end-to-end speedups: geometry,
+VAE work, and file writing still take time.
+
+## Training overview
+
+Training provenance, augmentations, and distillation design have moved to [Training and distillation](training.md).
+
+## Implementation map
+
+| Source | What to read |
+|---|---|
+| [`recam/geometry.py`](../recam/geometry.py) | `reconstruct`, `warp`, and `render_hw`: geometry filtering, projection, and visibility. |
+| [`recam/path.py`](../recam/path.py) | `plan_path` and `hermite`: keyframe interpolation, time mapping, and zero-roll look-at cameras. |
+| [`recam/h3.py`](../recam/h3.py) | `bucket`, `pack`, and `denoise`: canvases, reference conditioning, and the scheduler. |
+| [`inference/sample.py`](../inference/sample.py) | CLI time windows, parametric camera moves, diagnostics, and output files. |
+| [`service/app.py`](../service/app.py) | `prepare`, `geo`, and `do_render`: cached reconstruction and resident inference. |
+
+For weight provenance and modification notices, see [`MODIFICATIONS.md`](../MODIFICATIONS.md).
diff --git a/docs/release_checklist.md b/docs/release_checklist.md
new file mode 100644
index 0000000000000000000000000000000000000000..890a5016dc79cba1cd12ec2275caa3cf20f2ce44
--- /dev/null
+++ b/docs/release_checklist.md
@@ -0,0 +1,35 @@
+# Release preparation — internal checklist
+
+**Keep `Viggle/Meridian` private. Do not publish it without the user's explicit approval.**
+Release-facing wording does not authorize changing repository visibility.
+
+## Outstanding publication checks
+
+- Public-use clearance, including for the NBA footage and figures, remains pending. The presentation
+ examples are research previews; retain source credits and edit records before choosing publication assets.
+- Confirm and upload the intended transformer and LoRA weights before calling the model download complete.
+ The old `Viggle/Viggle-Recam` identifier was inaccessible during verification; do not restore it as a working download.
+- Low-memory configurations, including RTX 4090, are community integration targets, not validated support.
+- Fast point-cloud preview helps inspect an authored path; it does not guarantee generated-view fidelity.
+
+## Presentation and review
+
+- Replace local preview links with cleared publication assets.
+- Method video strips use actual matched frames; the 3D points and camera path are explicitly schematic. Retain this distinction and the source provenance.
+- Studio overview is recorded and preview-only; capture and review a matching generated take before extending it to demonstrate final generation.
+- Complete continuous visual motion review; automated playback and sampled frames are not sufficient.
+- Retain exact camera controls if presenting an isolated space/time ablation.
+- Confirm permission to use every source clip and to publish the corresponding demonstrations.
+- Keep source-time labels accurate when comparing live, retimed, and held sequences.
+- Verify the reported timing against a retained run log before publishing it as a headline result.
+- Do not add a speedup ratio, quality comparison, ablation, or metric without supporting results.
+- Hub destination: Viggle/Meridian (private). Do not point weight-download commands here until the weights are present.
+- Upload referenced presentation media with the Markdown; keep the private Hub snapshot separate from public-use clearance. The legacy push_docs.py targets a different repository.
+
+## Retained provenance
+
+- [Current example sources and edit notes](../videos-all/research_examples_v2/README.md)
+- [Teaser credits](../videos-all/longtake_showcase/TEASER_V7_NOTES.md)
+- [Method figure sources](assets/research/README.md#illustrated-method)
+- [Studio recording notes](studio_walkthrough.md)
+- [Training and distillation](training.md)
diff --git a/docs/research.html b/docs/research.html
new file mode 100644
index 0000000000000000000000000000000000000000..727c69691f7141e2db1416b1301905dbfa7bab5a
--- /dev/null
+++ b/docs/research.html
@@ -0,0 +1,242 @@
+
+
+
+
+
+Meridian: A new perspective on space and time
+
+
+
+Skip to article
+
+
+
Contents
+
+
+
+Meridian: A new perspective on space and time
+One event. Anywhere. Anytime.
+By Viggle AI
+14 September 2026.
+
+
+Meridian is a geometry-guided video model for authoring new observations of existing events.
+Given a video, choose a new camera path and the source moments to observe. Follow the action from
+another angle, linger on a gesture, or hold an instant while the camera keeps moving.
+Choose where. Choose when.
+
+Where: design the camera's position, viewing direction, and lens over a shot.
+When: let the action advance, hold a source moment, or change its pace by retiming the input.
+
+Bullet time is one possibility, not the whole idea. Camera motion and source time can be
+composed into different ways of watching the same event. A single image can also be the starting
+point for a moving view.
+The compound-camera example shows its source and requested path. The ballet examples use still images.
+
+
+
+
+ Watch the example .
+
+ A dunk. Source action, revisited from new angles. An edited sequence; dunk completion is source footage.
+
+
+
+ Watch the example .
+
+ Play. Hold. Resume. Linger on the splash, then let it continue.
+
+
+
+
+
+ Watch the example .
+
+ Compose a camera path. Widen, orbit, slide, approach, retreat—one uncut take.
+
+
+
+ Watch the example .
+
+ One image. Another viewpoint. A camera move from a single ballet image.
+
+
+
+
+
+ More examples · robots, animation, dance, and sport
+
+
+
+Method
+
+Matched source, warp, and output frames; the 3D points and cameras are schematic.
+The method is simple: use geometry to show a video model where to look.
+1. Reproject the source. VGGT-Omega estimates depth and source-camera poses. We build colored
+3D points, select the source moments, and project those points through an authored camera path
+into a warped video.
+2. Generate the new view. Meridian, built on MiniMax-H3, takes the source video and warped
+video , aligned to the same source moments, and generates the new shot. Geometry guides the view;
+the video model fills missing regions and refines appearance.
+Preview before generation. Once geometry is available, fast point-cloud rendering makes the
+chosen path visible. Check the framing, viewing direction, and uncovered regions—and adjust the
+camera before running the video model. This inexpensive preview is a useful consequence of making
+camera control explicit.
+Why this matters
+The shift is from generating another scene to choosing another observation of the same event .
+This is the world-model perspective behind Meridian: connect what we see to where and when we
+observe it, grounded in supplied footage rather than unrestricted simulation.
+Unseen regions are generated, not recovered. Geometry errors and large moves—including 360°
+orbits—can destabilize the view. Time edits revisit supplied frames, and separate takes need not
+form a consistent world.
+Try Meridian
+Get started with Meridian .
+Meridian uses MiniMax-H3 with precomputed text embeddings, without loading a text encoder .
+We welcome community work on quantization and CPU offloading toward smaller GPUs, including the
+RTX 4090; those configurations are not yet supported or validated by the provided implementation.
+The release also includes a very basic, vibe-coded Studio demo to illustrate how
+to use the model—not a production editor. It supports multi-key camera paths and real-time 3D
+preview, not real-time video generation.
+
+ Watch the 38-second Studio walkthrough
+
+
+ Watch the Studio walkthrough .
+
+
Authoring and geometric preview only, with some operations and waits omitted—not a final generated take.
+
+
+
+
+Powered by MiniMax H3. See the licenses and intended use .
+
+
+
+
diff --git a/docs/research.md b/docs/research.md
new file mode 100644
index 0000000000000000000000000000000000000000..5ec1bf712964c4ee560df8c4be9f0ebbac466298
--- /dev/null
+++ b/docs/research.md
@@ -0,0 +1,159 @@
+# Meridian: A new perspective on space and time
+
+**One event. Anywhere. Anytime.**
+
+By **Viggle AI**
+
+*14 September 2026.*
+
+
+
+**Meridian is a geometry-guided video model for authoring new observations of existing events.**
+Given a video, choose a new camera path and the source moments to observe. Follow the action from
+another angle, linger on a gesture, or hold an instant while the camera keeps moving.
+
+## Choose where. Choose when.
+
+- **Where:** design the camera's position, viewing direction, and lens over a shot.
+- **When:** let the action advance, hold a source moment, or change its pace by retiming the input.
+
+**Bullet time is one possibility, not the whole idea.** Camera motion and source time can be
+composed into different ways of watching the same event. A single image can also be the starting
+point for a moving view.
+
+The compound-camera example shows its source and requested path. The ballet examples use still images.
+
+
+
+
+
+ Watch the example .
+
+ A dunk. Source action, revisited from new angles. An edited sequence; dunk completion is source footage.
+
+
+
+ Watch the example .
+
+ Play. Hold. Resume. Linger on the splash, then let it continue.
+
+
+
+
+
+ Watch the example .
+
+ Compose a camera path. Widen, orbit, slide, approach, retreat—one uncut take.
+
+
+
+ Watch the example .
+
+ One image. Another viewpoint. A camera move from a single ballet image.
+
+
+
+
+
+ More examples · robots, animation, dance, and sport
+
+
+
+## Method
+
+
+
+*Matched source, warp, and output frames; the 3D points and cameras are schematic.*
+
+The method is simple: **use geometry to show a video model where to look.**
+
+**1. Reproject the source.** VGGT-Omega estimates depth and source-camera poses. We build colored
+3D points, select the source moments, and project those points through an authored camera path
+into a warped video.
+
+**2. Generate the new view.** Meridian, built on MiniMax-H3, takes **the source video and warped
+video**, aligned to the same source moments, and generates the new shot. Geometry guides the view;
+the video model fills missing regions and refines appearance.
+
+**Preview before generation.** Once geometry is available, fast point-cloud rendering makes the
+chosen path visible. Check the framing, viewing direction, and uncovered regions—and adjust the
+camera before running the video model. This inexpensive preview is a useful consequence of making
+camera control explicit.
+
+## Why this matters
+
+The shift is from generating another scene to **choosing another observation of the same event**.
+This is the world-model perspective behind Meridian: connect what we see to where and when we
+observe it, grounded in supplied footage rather than unrestricted simulation.
+
+Unseen regions are generated, not recovered. Geometry errors and large moves—including 360°
+orbits—can destabilize the view. Time edits revisit supplied frames, and separate takes need not
+form a consistent world.
+
+## Try Meridian
+
+[Get started with Meridian](../README.md#quickstart).
+
+Meridian uses MiniMax-H3 with precomputed text embeddings, **without loading a text encoder**.
+We welcome community work on quantization and CPU offloading toward smaller GPUs, including the
+RTX 4090; those configurations are not yet supported or validated by the provided implementation.
+
+The release also includes a **very basic, vibe-coded Studio demo** to illustrate how
+to use the model—not a production editor. It supports multi-key camera paths and real-time 3D
+preview, not real-time video generation.
+
+
+ Watch the 38-second Studio walkthrough
+
+
+ Watch the Studio walkthrough .
+
+
Authoring and geometric preview only, with some operations and waits omitted—not a final generated take.
+
+
+
+---
+
+Powered by MiniMax H3. See the [licenses and intended use](../README.md#license).
diff --git a/docs/studio.md b/docs/studio.md
new file mode 100644
index 0000000000000000000000000000000000000000..dcc4144fc6eb6316bb8b448db5b5481d7ff3d81a
--- /dev/null
+++ b/docs/studio.md
@@ -0,0 +1,210 @@
+# Studio: author a new shot
+
+[← Meridian](../README.md) · [Installation](installation.md) · [API](api.md) · [CLI](inference.md)
+
+The self-hosted studio lets you place cameras in a reconstructed scene, inspect the geometry reference,
+and generate a take without writing a command for every path revision.
+
+## What updates in real time?
+
+After reconstruction and point-cloud loading, the **browser's 3D view updates interactively** as you
+move cameras, change their aim or look through a key. This is the real-time authoring preview—not
+real-time generative video.
+
+The **full-path geometric-reference video** is refreshed by the server after a valid edit. It uses
+GPU warping and video encoding, and may wait behind reconstruction or generation on the same service.
+The **final generated take** is a separate job started with **Render this take**. No fixed preview
+latency or frame-rate guarantee is implied.
+
+## Start the service
+
+After [installation](installation.md), run from the release directory:
+
+```bash
+CARD=0 bash service/run.sh --host 127.0.0.1 --port 8412
+```
+
+Open `http://127.0.0.1:8412` after the terminal prints `ready`. Startup loads VGGT-Omega, the VAE,
+the finetuned teacher, and the student adapter onto one GPU; the previously reported B200 cold-start
+time is about 95 seconds. The active shell must have the VGGT-Omega environment variables set.
+
+If you downloaded the VAE locally, append `--model-dir ../MiniMax-H3`.
+
+**Keep the service private.** The program defaults to `0.0.0.0` when `--host` is omitted; the command
+above deliberately binds to loopback. The service has no authentication, per-user isolation, upload
+quota, or bounded durable job queue. For access to a remote machine, use an SSH tunnel or a protected
+deployment with authentication, resource limits, and the safeguards required by the model license.
+Do not expose this development service directly to the internet.
+
+## From clip to take
+
+### 1. Choose a clip and source window
+
+Upload an MP4/MOV/WebM or choose one of the sample clips. The service normalizes it to H.264,
+24 fps, and an aspect-preserving frame bounded by 1280 × 1280, with rotation baked in. Unlike the
+CLI, it performs this normalization automatically.
+
+The current page requires at least **73 normalized input frames**. It detects candidate hard cuts and
+prepares an initial window of at most **124 source frames**, stopping before the next detected cut.
+Cut detection is heuristic; split a clip manually if a cut is missed or a flash is mistaken for one.
+Moving the window's start reconstructs the new span and **resets the keys**.
+
+Select the take length separately. The page offers **73, 124, 175, or 243 output frames**; the CLI
+exposes all eight supported model lengths. A longer take does not automatically mean a longer source
+window or additional captured action.
+
+### 2. Start from a camera move
+
+Use a template: **orbit**, **push in**, **slide**, **crane**, **freeze + orbit**, or **the clip's own
+camera**. Templates replace the existing keys; **Ctrl+Z** undoes an edit.
+
+The source-camera template initializes editable endpoints; it is not an exact replay of every
+estimated source pose. Likewise, a template translated into a few keys is an editable approximation
+of its underlying parametric move. Inspect the resulting reference rather than assuming it matches
+a CLI command exactly.
+
+### 3. Refine the keys
+
+Each key chooses a camera and a time:
+
+| Control | Meaning |
+|---|---|
+| Camera position | Where to observe the scene from. Drag a camera in the 3D view. |
+| **aims at** | The key's look-at point. Use **pick in 3D** or **centre**. This does not change the reconstruction's depth scale. |
+| **clip frame it shows** | Source frame, indexed in the normalized uploaded clip. |
+| **output frame it lands on** | Position in the generated take. The first and last keys anchor its endpoints. |
+| **lens** | Horizontal field of view, converted to a multiplier over the selected source frame's estimated focal length. |
+
+Click a key's row or thumbnail to look through its camera; use **back to the overview** to see the
+whole path. While looking through a key, drag to aim, Shift-drag to translate, and scroll to dolly.
+Add a key at the preview frame to refine a segment. Camera roll is fixed to zero.
+
+### Go beyond a preset
+
+A path can combine several stages: **push forward → turn toward a detail → slide right → retreat**.
+Add a key at each change of intention, then set its position and look-at point in the shared 3D scene.
+Position and aim interpolate along cubic curves; the source-frame map is interpolated separately.
+This is different from ramping yaw, translation and dolly together in one CLI sweep.
+
+To let the camera travel while an instant holds, assign the same **clip frame it shows** to two or
+more keys at different output frames. Resume with a later source frame. Inspect every segment and
+the joins: several keys do not guarantee adequate geometry, subject visibility or generated continuity.
+The [walkthrough plan](studio_walkthrough.md#source-and-camera-design) includes a concrete timing
+sketch, not scene-independent camera coordinates or an already-generated demonstration.
+
+### 4. Inspect the reference
+
+After a valid edit, the studio re-warps the path before enabling generation:
+
+- **what the model sees:** the grey-hole geometry reference at conditioning resolution.
+- **where the pixels are missing:** the same view with missing regions highlighted in magenta.
+
+The reference is generated by the same geometry path used for inference. Its browser playback is a
+compressed visualization, not a pixel-exact copy of the tensor. Coherent framing and stable surfaces
+matter more than a low missing-pixel percentage. Pay special attention to faces, thin structures,
+subject silhouettes, and new surfaces revealed by the camera.
+
+### 5. Render and compare
+
+Choose **Render this take** after checking the path. The service performs VAE encoding, three student
+forwards, decoding, and video writing; progress appears on the render screen. Generation recomputes
+the warp rather than reading the preview MP4 back into the model.
+
+The take screen shows the selected source timeline, geometry reference, and generated shot in sync.
+Download `out.mp4` or the three-up `grid.mp4`. Service outputs have no soundtrack; the CLI's
+`out_audio.mp4` muxing workflow is not part of the studio. Camera archives (`cams.npz`) are CLI-only.
+
+## Source time and output time
+
+The keyframe representation is `{pos, look, src, t, ease, focal}`. `src` is an absolute source index;
+`t` is an output index. Between two keys, the source rate is:
+
+```text
+rate = (next.src - current.src) / (next.t - current.t)
+```
+
+- **Rate 1:** preserve the uploaded video's pace, including any slow motion or speed-up already
+ baked into that video.
+- **Rate 0:** hold one instant while the camera may move.
+- **Other positive rates:** interpolate the source indices and round to frames, duplicating or
+ skipping them. The UI warns outside holds and approximately 1:1 playback; this is not a motion
+ interpolation system.
+- **Negative rates:** rejected. Source keys must never run backward.
+
+For slow motion or speed-ups, use the [24 fps source-retiming workflow](inference.md#slow-motion-and-speed-ups)
+first, then author a 1:1 path over that export. A warning about a keyframe segment does not mean
+pre-retimed footage is unsupported.
+
+**Check long takes carefully.** The page prepares at most 124 source frames. If you stretch that
+entire source window across a 243-frame take with two endpoints, the source advances at roughly
+half speed; it does not play 124 frames normally and then automatically hold. To preserve pace,
+place an explicit key where live motion ends, followed by a hold, or use the CLI with enough
+pre-retimed input frames. Changing take length or choosing a template can change these rates.
+
+## Preview checks
+
+The page enables rendering only after the latest valid warp passes these checks:
+
+| Check | Current threshold |
+|---|---|
+| Clearance proxy | `ahead >= -0.1`, in pivot-depth units. |
+| Difference from source camera | Translation `moved > 0.004`, key orientation change `turned > 0.5°`, or focal change `zoomed > 0.01`. |
+
+`ahead` is the minimum over time of the fifth-percentile target-camera depth for valid points in
+the central source region. It helps flag fly-throughs; it is **not** a complete collision test or a
+guarantee that the camera stays outside every surface. `moved` measures departure from the source
+camera, not whether the target camera travels over time. A different but stationary view can pass.
+
+The missing-pixel percentage is informative, not a gate. A pure focal change may pass the motion
+check while still being ignored by the model.
+
+**These clearance and camera-change checks live in the browser, not `/render`.** API clients must
+inspect previews and validate their own requests; calling `/render` bypasses the page's checks.
+The API also does not enforce the page's cut-aware 124-frame window policy.
+
+## Memory and lifecycle
+
+One process owns one GPU. A lock serializes GPU work, including preparation, previews, and generation;
+multiple requests do not yield concurrent GPU inference. Render requests start background threads
+that can wait on the lock, but there is no bounded queue, cancellation API, or durable job scheduler.
+Run **one worker**, not multiple Uvicorn workers that each load a model copy.
+
+| Option | Default | Purpose |
+|---|---|---|
+| `--host`, `--port` | `0.0.0.0`, `8412` | Listen address; use loopback unless the deployment is protected. |
+| `--work` | `/work` | Uploads, preview files, and generated takes. |
+| `--samples` | `/examples/media` | Sample MP4s listed on the first screen. |
+| `--max-clips` | `8` | Maximum number of decoded clips in the in-memory clip cache. |
+| `--max-prep` | `8` | Maximum number of prepared source spans in the geometry cache. |
+| `--ckpt`, `--lora` | Release directories | Teacher and student adapter. The service always loads an adapter. |
+| `--model-dir` | `MiniMaxAI/MiniMax-H3` | VAE location. |
+| `--vggt-repo`, `--vggt` | Environment-based | Geometry code and checkpoint. |
+| `--steps`, `--flow-shift` | `4`, `3` | Keep these at the student sampling settings for this release. |
+
+Prepared spans retain tensors on the GPU, and cache limits count **entries**, not bytes. Memory can
+grow as you explore different windows. Lower `--max-prep`, use shorter windows, or restart to release
+old sessions when operating near the memory limit. Reported single-take peaks do not bound a
+long-running service with many cached spans.
+
+`service/run.sh` restarts the process only after exit code `3`, used for a poisoned CUDA context.
+Other exits stop the wrapper. Clip, preparation, and job registries are in memory: a restart loses
+the live session even if files remain on disk. Re-upload/select the clip and prepare it again.
+Evicted clips or prepared spans can similarly invalidate older browser tabs.
+
+Generated files are not automatically expired. Monitor `/clips`, `/warp`, and
+`/takes`; stop the service before manually removing data still referenced by an active session.
+Keep uploaded footage private and use material you have permission to process.
+
+## Troubleshooting the studio
+
+| Symptom | Next step |
+|---|---|
+| Render is disabled | Wait for the latest warp, check key order and source direction, then inspect the clearance and camera-change messages. |
+| The take unexpectedly slows down | Compare source and output indices, especially after choosing 175/243 frames or applying a template. |
+| Preparation fails near a cut | Move to a continuous span with at least two source frames, or trim and upload the shot separately. |
+| An old tab starts failing | Its cached clip or span may have been evicted, or the service restarted. Select the clip again. |
+| Previews stop while a take renders | GPU work is serialized; there is no separate preview GPU. |
+| Memory rises over a session | Reduce the prepared-span cache or restart; source-window length and cached tensors matter as well as output length. |
+| Page reports a GPU restart | Watch the terminal for `ready`, then start a new session. Previous job IDs will not be restored. |
+
+See [Installation](installation.md#setup-problems) for dependencies and [API](api.md) for programmatic use.
diff --git a/docs/studio_walkthrough.md b/docs/studio_walkthrough.md
new file mode 100644
index 0000000000000000000000000000000000000000..0087dfd68b8cd430115a9face505e72756cd1226
--- /dev/null
+++ b/docs/studio_walkthrough.md
@@ -0,0 +1,251 @@
+# Meridian Studio — walkthrough film
+
+[← Research article](research.md#try-meridian) · [Studio guide](studio.md)
+
+**Status: a 38-second preview-only overview is available; a matching generated take is still pending.**
+[Watch the concise Studio overview](../videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise.mp4)
+· [Editing recipe](../videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/edit.json).
+
+The concise edit uses restrained English titles and enlarged details of the actual UI:
+**one source → camera position and aim → held source time → geometric reference**.
+It omits repetitive authoring and backend waits, disclosed on screen, without accelerating the
+remaining actions. The complete supplied input and 243-frame geometric reference are retained;
+the UI capture is resampled from 25 to 24 fps. It is silent, with no final generated video implied.
+The original recording remains unchanged:
+
+[Watch the revised, uncut recording](../videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_review.mp4)
+· [10-second geometric reference](../videos-all/studio_walkthrough/nba3_preview_live_02/preview_truth.mp4)
+· [Before / after camera comparison](../videos-all/studio_walkthrough/nba3_preview_live_02/review_camera_comparison.jpg)
+· [Session evidence](../videos-all/studio_walkthrough/nba3_preview_live_02/session.json).
+
+NBA3 replaces the flower scene as the current walkthrough candidate: approach → airborne hold with
+camera travel → resumed dunk and landing. The
+[earlier flower pilot](../videos-all/studio_walkthrough/flowers_preview_live_01/studio_walkthrough_review.mp4)
+is retained, not overwritten.
+
+**Revision 02 replaces the large orbit/approach with small athlete-framed lateral travel.**
+The athlete and hoop are substantially more legible in the held reference, and the source map
+continues through the dunk and landing. Review included contact sheets covering all 243 reference
+frames and larger comparisons at output frames 60, 134 and 179. The backend's average coverage
+rose from 61.2% to 83.9%; that is a geometric diagnostic, not a generated-quality score.
+
+**The reference still has conspicuous disocclusion holes and tearing around the athlete's outline.**
+This is a more useful authoring demonstration, not an approved cinematic result. Native-speed motion
+review and a matching generated take are still needed before publishing the research-page film.
+The [rejected first camera pilot](../videos-all/studio_walkthrough/nba3_preview_live_01/studio_walkthrough_review.mp4)
+is retained for comparison, not silently replaced.
+
+The September 13 recordings ran through Chromium against the existing Studio at `127.0.0.1:8412` on GPU 0,
+with permission to execute outside the restricted sandbox. It records actual seven-key authoring and
+geometric previews; **no final generation was submitted**. The running main-repository Studio has
+the same authoring controls as the release, with minor comment/warning-text differences; the served
+HTML is retained. Revision 02 completed 81 POST requests with no recorded API/browser errors and
+no `/render` request. The preview workflow passed its live checks; the script's `--render` branch remains
+untested. This is raw workflow evidence, not yet an approved research-page film.
+
+The older files named `browser_studio.png` are screenshots of a separate source/control gallery,
+not this camera-authoring application. Do not substitute them for a Studio demonstration.
+
+## Record with Playwright
+
+[Recording script](record_studio_walkthrough.py) — run it in a terminal where Chromium can launch
+and `http://127.0.0.1:8412` is reachable. That address means **the machine running the script**;
+use an existing private tunnel or `--url` if the Studio runs elsewhere. Do not expose the unauthenticated
+service publicly. The script connects to an existing service; it does not launch, restart or cancel it.
+
+**Arrange a free service/GPU slot first.** Even without `--render`, uploading triggers reconstruction,
+and editing triggers point-cloud, thumbnail and full-path warp work. The script waits between edits;
+it is not a CPU-only recording tool and cannot determine whether other users need that GPU.
+
+From the release root, make a preview-only pilot:
+
+```bash
+PY=/home/chenyun/miniforge3/envs/wan_new/bin/python
+"$PY" docs/record_studio_walkthrough.py \
+ --source videos-all/nba3_teacher30/nba3_full_event.mp4 \
+ --camera-style nba-glide \
+ --url http://127.0.0.1:8412 \
+ --out videos-all/studio_walkthrough/nba3_preview_02
+```
+
+This NBA3 plate contains the complete event in **124 frames at 24 fps**, already prepared from the
+supplied clip. The hold uses frame 60, during the airborne ball sweep before the dunk; the action
+then resumes through the landing. For another scene, choose a clean clip with at least 124 normalized frames
+before its first detected cut. It stops if that prepared span is shorter; it does not silently adapt
+the timing sketch. Retain source permission/attribution when substituting footage.
+
+The pilot uses actual UI controls to:
+
+1. Upload and reconstruct, select 243 output frames, then start from the source-camera path.
+2. Add and retime five intermediate keys using the source-time table below.
+3. Look through keys, make small sideways Shift-drags, and adjust the aim to retain the athlete and hoop.
+4. Return to the overview, scrub the hold, and play the real grey-hole and magenta references.
+
+`nba-glide` is **specific to the NBA3 full-event plate**. It reads the reconstructed torso point near
+normalized source-image coordinate `(0.367, 0.435)` at frame 60, then uses genuine pointer gestures
+to place it near `(0.40, 0.435)` during the hold. This preserves space for the ball and hoop rather
+than aiming every key at the scene centre. It does not inject camera state or replace UI responses.
+Read-only projection calculations guide the automated gestures; this is not an automatic subject-tracking feature.
+
+Nominal sideways offsets reach 0.024 scene-centre-depth units, with no forward push. Exact positions
+and aims are retained in `path_preview.json`; these depth-normalized units are not metres.
+The older nominal 30° orbit workflow remains available as `--camera-style orbit-pilot` (the script's
+default for compatibility), **not as the recommended NBA3 path**. Neither workflow is a
+reproduction of an approved CLI take, a large-angle benchmark or a guarantee of generated quality.
+Inspect both downloaded reference videos continuously before spending time on final generation.
+Passing the Studio's clearance gate is not a visual-quality verdict.
+
+To capture the same scripted workflow **including a new generated take**, use a new directory and
+add `--render`:
+
+```bash
+"$PY" docs/record_studio_walkthrough.py \
+ --source videos-all/nba3_teacher30/nba3_full_event.mp4 \
+ --camera-style nba-glide \
+ --out videos-all/studio_walkthrough/nba3_render_01 \
+ --render
+```
+
+This is a new session, not a resume of the preview. The script retains and checks the accepted job's
+payload against the path displayed in **that recording**. It never bypasses a disabled Render button.
+Add `--headed` to watch in Chromium on a machine with a display; let the automation finish without
+editing the same page. Default headless mode records the same viewport without needing a desktop.
+`--timeout` sets each backend wait in seconds; the default is 1800. A timeout or closed browser
+**does not cancel an already submitted job**. Check its recorded job ID before retrying.
+
+If Playwright or Chromium is missing, install them in the recording environment first:
+
+```bash
+"$PY" -m pip install playwright
+"$PY" -m playwright install chromium
+```
+
+### What gets saved
+
+- `studio_walkthrough_raw.webm`: the actual 1920 × 1080 browser viewport, **including real waits**.
+ It records neither browser chrome nor audio; do not rely on it to include the OS mouse cursor.
+ No fake cursor, replacement UI, simulated responses or accelerated preview are injected.
+- `input.*` and, when present, `input_provenance.json`: a retained upload and its adjacent source record.
+- `prepared.json`, `path_preview.json`, `warp_preview.json`: the normalized span, geometry, exact
+ edited keys, source-frame map and preview diagnostics. Preview-only runs do not claim a render payload.
+- `preview_truth.mp4`, `preview_holes.mp4`, numbered screenshots: reference footage and review stills.
+- With `nba-glide`, `subject_anchor.json`: the selected reconstructed torso point and its source projection.
+- `session.json`, `studio_served.html`: source/download hashes, served UI, request payloads and
+ client-observed wall-clock milestones. These timestamps are relative to script startup, **not exact
+ WebM edit points or an interactive-latency benchmark**.
+- With `--render`: `render_request.json`, `job.json`, and the matching `source.mp4`, `render.mp4`,
+ `out.mp4`, `grid.mp4`. `source.mp4` follows the authored source-time map; it is not the untouched input.
+
+The API does not expose checkpoint identities or the launch recipe. Retain the service launch command,
+checkpoint/adapter identifiers and server log separately. Also preserve the normalized upload from
+`/clips//clip.mp4` if an exact input archive is needed; `` is recorded in
+`prepared.json`. The script does not inspect the server filesystem or guess its configuration.
+
+For an MP4 viewing copy, without cutting waits or changing playback speed:
+
+```bash
+ffmpeg -n -i videos-all/studio_walkthrough/nba3_render_01/studio_walkthrough_raw.webm \
+ -c:v libx264 -crf 18 -pix_fmt yuv420p -movflags +faststart \
+ videos-all/studio_walkthrough/nba3_render_01/studio_walkthrough_review.mp4
+```
+
+Keep the raw recording. A 45-second research-page film is a **separate editorial pass**, following
+the outline below, with omitted waits disclosed. Use the downloaded full `out.mp4` for the cinematic
+reveal, not a screen-recorded crop of its small comparison pane. Do not publish a Studio-film link
+until the actual recording and generated motion have been reviewed.
+
+## The story
+
+**Design the observation. See the reference. Generate the shot.**
+
+One beautiful source, one deliberate camera path, one uninterrupted generated result. Show that the
+released Studio is an authoring tool—not only a gallery or a menu of orbit presets. The point is the
+relationship between an edit and its visible consequence, rather than a tour of every control.
+
+Place the film in the research article's Studio section, after the method and speed discussion.
+Keep the cinematic hero separate: the hero shows the result; this film explains how to author it.
+
+## Capture outline · approximately 45 seconds
+
+These are editorial allocations, **not measured service timings**. Extend the capture if an operation
+needs longer; do not speed up pointer movement or pretend the model generated instantaneously.
+
+| Passage | Actual screen action | Minimal caption |
+|---|---|---|
+| Establish · 0–4 s | Show the chosen source, then the actual Studio with a prepared source span. The source must remain identifiable. | One source. A new observation. |
+| Author · 4–16 s | Show the multi-key path, look through a key, Shift-drag sideways and adjust its aim. Keep the athlete and hoop legible; do not exaggerate the small travel. | Place the camera. Shape its path. |
+| Shape time · 16–23 s | Show two keys sharing a source frame at different output frames. Scrub across the hold and the subsequent advancing segment. | Hold the moment. Keep the camera moving. |
+| Inspect · 23–29 s | Let the genuine full-path warp finish. Play the grey-hole reference; briefly switch to the magenta diagnostic. Keep one actual edit-to-preview response at native speed. | Preview the geometry before generating. |
+| Generate · 29–32 s | Click **Render this take** and show the real progress screen. If waiting is cut, say so and report the retained run's elapsed time. | Generation wait omitted: [measured duration]. |
+| Reveal · 32–42.125 s | Play the matching 243-frame output intact at 24 fps, large and uncluttered. | Generated view. |
+| Close · about 3 s | End on the Studio's source / reference / output comparison or a quiet wordmark. | Meridian Studio · included in the code release. |
+
+The final take must be generated from **the exact Studio keys shown**. An existing CLI flower or
+motorcycle output is useful for choosing a scene, but is not evidence of an unexecuted Studio path.
+
+## Source and camera design
+
+**NBA3 is the current walkthrough source.** Its wide view makes the approach, airborne ball sweep,
+dunk and landing legible as one event. The retained 124-frame plate covers the full supplied clip;
+its frame 60 maps to original frame 73 / PTS 2.435767 s. See the
+[exact input preparation](../videos-all/nba3_teacher30/provenance.json). These are source-file
+timestamps, not a claim about physical capture speed. The footage is user-supplied; public
+redistribution rights and endorsement have not been established.
+
+The *Spring* flower scene remains an alternate, with Blender Foundation attribution and CC BY 4.0
+notice in [its input preparation](../videos-all/longtake_edit/plates/flowers_linger243.json).
+
+Use a source export appropriate for the Studio's **maximum 124-frame prepared window**. Do not claim
+the Studio reproduced a 243-source-frame CLI reconstruction; selecting a 243-frame *output* does
+not enlarge its prepared source window. Begin with a modest, well-framed path. Only increase travel
+after inspecting the projection—an impressive trajectory that loses the athlete is a worse demo.
+
+For a 124-frame prepared span starting at `start`, this **timing sketch** fits a 243-frame output:
+
+| Output index `t` | Source index | Camera intention, to tune in the actual scene |
+|---|---|---|
+| 0 | `start + 0` | Establish the source-side composition. |
+| 40 | `start + 40` | Follow the source framing with a small lateral offset. |
+| 60 | `start + 60` | Begin the time hold with breathing room around the subject. |
+| 105 | `start + 60` | Glide sideways while retaining the athlete. |
+| 145 | `start + 60` | Travel sideways, keeping the aim on the subject. |
+| 179 | `start + 60` | Ease back toward the source-side camera before action resumes. |
+| 242 | `start + 123` | Let the action advance again. |
+
+This uses all 124 prepared source frames and adds 119 held output frames. It preserves the prepared
+input's pace outside the hold; any slow motion already in that input remains baked in. The exact
+camera keys are saved with each recording. This table specifies intent, not a promise of seamless
+generated motion.
+
+## What “real-time preview” may honestly mean
+
+- **Browser 3D view:** a loaded point cloud and camera handles redraw during interaction. Capture
+ this normally; do not attach an FPS or latency claim without measuring it.
+- **Full-path geometric reference:** generated by the backend after a committed valid edit. This
+ requires GPU work and video encoding; it can wait behind other service work.
+- **Final generated video:** a separate render job. Never label its replay as a live model response.
+
+The point-cloud overview is not the full conditioning tensor. The grey-hole video is a compressed
+preview of that reference; the magenta view is diagnostic and is not given to the model.
+
+## Capture and acceptance checklist
+
+- Record the actual released `service/index.html`, not a UI mock or the `videos-all` gallery.
+- Arrange a dedicated service/GPU recording slot separately. Do not interrupt existing jobs to make
+ this recording. No service was started or render queued as part of this documentation update.
+- Capture at native 1920 × 1080 or another readable desktop size. Keep pointer motion deliberate;
+ show the key table when explaining source time. Avoid cinematic overlays on the actual output.
+- Retain the source export, normalized frame window, exact `/render` path payload, seed, model
+ recipe, output files and status timings alongside the raw capture. The UI has no path-export
+ button, so retain the request through browser network tools or the client used for the session.
+- Disclose omitted reconstruction/generation waits. Keep one representative edit-to-warp update
+ unaccelerated, including its real waiting time. Cold reconstruction is not interactive preview.
+- Check subject visibility, transitions into/out of the hold, thin geometry and newly exposed
+ backgrounds continuously. Sampled frames and successful playback alone are insufficient.
+- Confirm the generated take matches the recorded path and source map. Record any crops or omitted
+ output frames; the first choice is to keep the complete generated take intact.
+- Add source credits and transformation notices. Do not imply that a view inferred from a film is
+ documentary footage, or that a nominal orbit angle was measured in the generated output.
+
+Once recorded and reviewed, add a real poster and MP4 link to the research article. Until then,
+link this plan explicitly as a plan; no broken “Watch Studio” button or fabricated placeholder video.
diff --git a/docs/training.md b/docs/training.md
new file mode 100644
index 0000000000000000000000000000000000000000..ee37d88cdafe30d4397042ccfef1ea353180c8e8
--- /dev/null
+++ b/docs/training.md
@@ -0,0 +1,46 @@
+# Training and distillation
+
+[← Meridian](../README.md) · [Inference method](method.md)
+
+Training provenance and design are collected here rather than in the model card or research blog.
+
+## Training overview
+
+The following is the release's training description; this repository contains inference code and
+artifacts, **not the training or distillation pipeline**.
+
+The teacher was trained on
+[MultiCamVideo](https://huggingface.co/datasets/KwaiVGI/MultiCamVideo-Dataset): 13,600 Unreal Engine
+scenes, each filmed by ten synchronized cameras over 81 frames. A sample pairs one camera's clip
+with a point-cloud render from a second camera; the second camera's actual clip is the target.
+Both directions of camera pairs are used, and geometry is reconstructed from the source clip alone.
+
+Later stages added still-frame references, temporally extended examples made by slowing, reversing,
+or holding the 81-frame window, and eased sweeps. The student was distilled at 73, 90, and 124 frames,
+with 243-frame holds also reported. Training-time temporal augmentation is not a promise that every
+time mapping or reverse-playback path is supported by the released interfaces.
+
+## Distillation and checkpoint design
+
+The release has two learned components:
+
+| Component | Role |
+|---|---|
+| `transformer/` | Fully finetuned MiniMax-H3 teacher: stock `fl2va` architecture, 50 layers, hidden size 5376; reported weight size 61.7 GiB in bf16. |
+| `lora/` | Rank-128 DMD student adapter on **that finetuned teacher**, reported size 2.5 GiB. It is not an adapter for the unmodified base transformer. |
+
+| Mode | CLI settings | Transformer evaluations |
+|---|---|---|
+| Student, default | `--steps 4 --flow-shift 3` with the LoRA loaded | 3 |
+| Teacher | `--no-lora --steps 50 --flow-shift 12` | 49 |
+
+The H3 scheduler counts the terminal zero-noise point in `--steps`. That endpoint does not require a
+model evaluation, hence four grid points produce three forwards. Reducing the teacher's step count
+is not equivalent to using the distilled student. Forward counts also do not directly translate to
+end-to-end speedups: reconstruction, warping, VAE work, and file writing still take time.
+
+The source and point-cloud-rendered references share the selected source timeline. Synchronized
+multi-camera supervision is followed by temporal and camera-path augmentation and student distillation.
+The training footage is synthetic; real-world performance depends on the scene.
+
+For weight provenance and modification notices, see [`MODIFICATIONS.md`](../MODIFICATIONS.md).
diff --git a/examples/CREDITS.md b/examples/CREDITS.md
new file mode 100644
index 0000000000000000000000000000000000000000..3fcacca59ef947e48c34c1472c34fbeebec2c5e0
--- /dev/null
+++ b/examples/CREDITS.md
@@ -0,0 +1,13 @@
+# Sample clips
+
+Both clips in `media/` are from Wikimedia Commons and were released by their uploaders under
+[CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/) (public domain dedication). We modified
+them: cut to a 73-frame window, scaled to 1280 × 720, re-encoded as H.264, soundtrack removed.
+
+| file | source | uploader | window |
+|---|---|---|---|
+| `sp_bouldering_hang.mp4` | [2020-11-28 - IFSC Euros - Combined M-B - Alex Khazanov - Video 3.webm](https://commons.wikimedia.org/wiki/File:2020-11-28_-_IFSC_Euros_-_Combined_M-B_-_Alex_Khazanov_-_Video_3.webm) | Voltmetro | from 9.5 s |
+| `sp_bouldering_reach.mp4` | [Anna Stohr JMM 2013 Annecy Bloc.webm](https://commons.wikimedia.org/wiki/File:Anna_Stohr_JMM_2013_Annecy_Bloc.webm) | Shev123 | from 13.75 s |
+
+Both show identifiable athletes at public competitions. The CC0 dedication covers the uploader's
+copyright, not the athletes' personality rights; the clips are here as technical demo inputs only.
diff --git a/examples/media/sp_bouldering_hang.mp4 b/examples/media/sp_bouldering_hang.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..e8ed835fb50f316601e91aa6ecb062c6da4d412a
--- /dev/null
+++ b/examples/media/sp_bouldering_hang.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6e79aa0bf6f57695c05c5d46dd057b35fb18b1a50f266de0426d087733710fe7
+size 2426274
diff --git a/examples/media/sp_bouldering_reach.mp4 b/examples/media/sp_bouldering_reach.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..5f3d1a498683bb9d355cb8cf2248cc312d724db7
--- /dev/null
+++ b/examples/media/sp_bouldering_reach.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2b6512d0c8191510a818a821106ec1ef7d921745f4896f34f9d2abc6a3054285
+size 4635267
diff --git a/inference/sample.py b/inference/sample.py
new file mode 100644
index 0000000000000000000000000000000000000000..c430305e32d1e1a3e4b10ef6cb3e0d16b629a038
--- /dev/null
+++ b/inference/sample.py
@@ -0,0 +1,298 @@
+# Copyright 2026 Viggle AI. Licensed under the Apache License, Version 2.0 (see LICENSE-CODE).
+# SPDX-License-Identifier: Apache-2.0
+"""Re-camera a video from the command line: source clip + an authored camera move -> the model's video.
+
+ # 3-forward DMD student (the default weights of this repo):
+ python inference/sample.py --video clip.mp4 --yaw 15 --sweep --out out/clip_yaw15
+ # 50-step teacher, no LoRA:
+ python inference/sample.py --video clip.mp4 --yaw 15 --sweep --no-lora --steps 50 --flow-shift 12 --out out/t
+
+The clip is letterboxed into a 1280x1280 frame (`FULL`), reconstructed by one VGGT-Omega pass, and re-rendered
+from a second camera rigidly attached to the source camera: `c2w_dst[t] = c2w_src[t] @ delta(t)`, where `delta`
+orbits about the pivot at frame 0's median depth (`--yaw`, degrees) and/or trucks sideways (`--truck`, in units of
+that depth). `--sweep` ramps `delta` from identity at frame 0 to its full value at the last frame, so a static
+source camera turns into a moving one. `--freeze F:N` is bullet time: the window is `start..F-1`, then source
+frame `F` held for `N` frames while `delta` ramps from identity to its full value, then `F+1..` for whatever is
+left of the window; the frozen frames share `F`'s geometry, so the render is a moving camera over a static cloud.
+The render uses the source's own per-frame intrinsics -- there is no target clip to take them from.
+
+`--video` may also be a still image (PNG), which with `--freeze 0:73` makes the whole window that one frame.
+
+Writes to `--out`: out.mp4, out_audio.mp4 (source soundtrack of the same window muxed back on; not for `--freeze`),
+render.mp4, source.mp4, grid.mp4 = [source | render | out] at the target canvas, last.png = out's final frame, and
+cams.npz with the source and target cameras.
+"""
+
+import argparse
+import math
+import os
+import subprocess
+import sys
+import time
+
+import av
+import numpy as np
+import torch
+from diffusers import AutoencoderKLMiniMaxH3, MiniMaxH3Transformer3DModel
+from diffusers.utils.export_utils import encode_video as write_mp4
+from PIL import Image
+
+ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+sys.path.insert(0, ROOT)
+import recam.geometry as geo # noqa: E402
+from recam.geometry import FULL, LENGTHS, NUM_FRAMES, RES, reconstruct, resize_u8, to_input, vggt, warp # noqa: E402
+from recam.h3 import FPS, bucket, decode_video, denoise, encode_video, pack # noqa: E402
+
+ASSETS = f"{ROOT}/assets"
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--video", required=True)
+parser.add_argument("--ckpt", default=f"{ROOT}/transformer", help="the finetuned transformer (a diffusers `transformer/` dir)")
+parser.add_argument("--model-dir", default="MiniMaxAI/MiniMax-H3", help="the base MiniMax-H3 repo or a local copy of it, for `vae/`")
+parser.add_argument("--start", type=int, default=0, help="first source frame of the 73-frame window")
+parser.add_argument("--yaw", type=float, default=0.0, help="orbit about the frame-0 median-depth pivot, degrees; + moves the camera left")
+parser.add_argument("--yaw-from", type=float, default=0.0, help="with --sweep/--freeze: ramp the yaw from this value instead of 0 (the lead-in holds it)")
+parser.add_argument("--truck", type=float, default=0.0, help="sideways camera shift in units of the pivot depth; + moves right")
+parser.add_argument("--sweep", action="store_true", help="ramp the offset linearly from 0 at frame 0 to its full value at the last frame; with --freeze the live lead-in and tail orbit too, at --live-speed")
+parser.add_argument("--freeze", default=None, help="F:N -- hold source frame F for N frames and ramp the offset over them (bullet time)")
+parser.add_argument("--live-speed", type=float, default=0.33, help="with --freeze --sweep: angular speed of the live lead-in and tail relative to the frozen frames")
+parser.add_argument("--swing", action="store_true", help="sine ramp 0 -> 1 -> 0 -> -1 -> 0: orbit to one side, back through the source camera, out to the other side and back")
+parser.add_argument("--ease", action="store_true", help="cosine ease-in-out on the ramp (start and end at rest)")
+parser.add_argument("--bounce", action="store_true", help="there-and-back ramp 0 -> 1 -> 0 (cosine), so the chunk starts and ends at the source camera")
+parser.add_argument("--dolly", type=float, default=1.0, help="orbit radius as a fraction of the pivot depth, reached along the ramp; focal scales with r so the pivot plane keeps its size (dolly zoom: closer and wider)")
+parser.add_argument("--zoom", type=float, default=0.0, help="final focal multiplier, reached along the ramp; overrides the dolly's automatic focal scaling. --dolly 0.6 --zoom 1 is a true push-in (parallax, subject grows); --dolly 1 --zoom 1.6 is a pure optical zoom")
+parser.add_argument("--boom", type=float, default=0.0, help="vertical camera shift in units of the pivot depth; + raises the camera (crane up)")
+parser.add_argument("--pivot", default=None, help="fx,fy -- put the orbit pivot at the depth seen there (fractions of the crop box, frame 0); default: median depth")
+parser.add_argument("--aim", action="store_true", help="after boom/truck/dolly, rotate the camera to put the pivot back where it was on screen (a crane that keeps looking at the subject); a no-op for pure --yaw with --pivot-lock")
+parser.add_argument("--pivot-to", default=None, help="fx,fy -- a second picked pixel: with --aim, the camera pans/tilts off --pivot and ends up looking AT this point (it lands in frame centre). Pure rotation; orbit/boom/truck still use --pivot")
+parser.add_argument("--pivot-lock", action="store_true", help="with --pivot: orbit about that 3D point instead of the optical axis, so an off-centre subject keeps its screen position")
+parser.add_argument("--follow", action="store_true", help="replay the input clip's OWN estimated camera path over the geometry of frame --start alone: one VGGT pass gives both, so the path and the cloud share a gauge. Ignores --yaw/--truck/--dolly/... -- the trajectory comes from the video")
+parser.add_argument("--smooth", type=float, default=8.0, help="with --follow: Gaussian sigma in frames used to low-pass VGGT's per-frame poses (translation, rotation and focal). VGGT estimates every frame independently, so the raw path jitters; 0 disables")
+parser.add_argument("--cull", action="store_true", help="drop splats the target camera sees from behind (depth-map normal oriented to the source camera), so a 180-degree view is a hole, not the mirrored front")
+parser.add_argument("--fast-back", type=float, default=1.0, help="K>1: sweep the middle half of the yaw range (the unobserved back) K times faster than the two observed quarters")
+parser.add_argument("--seed", type=int, default=1234)
+parser.add_argument("--gauge-only", action="store_true", help="stop after the geometry diagnostics (fly-through gauge, pivot depth, coverage) -- no VAE, no transformer, no render")
+parser.add_argument("--canvas", default="", help="render at an explicit WxH (multiples of 32) instead of the 768-class bucket. The rotary grid is normalised by sqrt(area), so the same aspect at a larger canvas keeps the position ids in distribution -- only the sampling density changes. Raise --full with it or the warp is upsampled from a 1280 source")
+parser.add_argument("--full", type=int, default=0, help="side of the square the source is letterboxed into, default 1280 (the corpus's). Raise it alongside --canvas so the point cloud is unprojected and resampled at the output resolution")
+parser.add_argument("--steps", type=int, default=4, help="scheduler timesteps: 4 = the student's 3 forwards")
+parser.add_argument("--lora", default=f"{ROOT}/lora", help="the DMD student, a LoRA on the teacher passed as --ckpt; its grid is --steps 4 --flow-shift 3")
+parser.add_argument("--no-lora", action="store_true", help="run the teacher alone (then --steps 50 --flow-shift 12)")
+parser.add_argument("--flow-shift", type=float, default=3.0, help="video scheduler shift: 3 for the student, 12 (MiniMax-H3's) for the teacher")
+parser.add_argument("--frames", type=int, default=NUM_FRAMES, choices=LENGTHS, help="output length in frames (the lengths assets/ has a prompt embed for)")
+parser.add_argument("--attn-backend", default="_native_cudnn")
+parser.add_argument("--vggt", default=None, help="vggt_omega_1b_512.pt; default $VGGT_OMEGA_CKPT (see README)")
+parser.add_argument("--vggt-repo", default=None, help="a checkout of facebookresearch/vggt-omega; default $VGGT_OMEGA_DIR")
+parser.add_argument("--out", required=True)
+args = parser.parse_args()
+if args.full: # `warp` scales VGGT's intrinsics by the module global, so both names must move
+ geo.FULL = FULL = args.full
+NUM_FRAMES = args.frames
+device = torch.device("cuda")
+torch.set_grad_enabled(False)
+os.makedirs(args.out, exist_ok=True)
+torch.manual_seed(args.seed)
+
+# --- the clip, letterboxed into the corpus' square frame -------------------------------------------
+# `tmap[t]` is the source frame shown at output frame t; only the distinct frames are decoded and reconstructed.
+if args.freeze:
+ fz, n = map(int, args.freeze.split(":"))
+ tail = NUM_FRAMES - n - (fz - args.start)
+ assert fz >= args.start and tail >= 0, f"freeze {fz}x{n} does not fit a {NUM_FRAMES}-frame window from {args.start}"
+ tmap = list(range(args.start, fz)) + [fz] * n + list(range(fz + 1, fz + 1 + tail))
+ ramp = torch.cat([torch.zeros(fz - args.start), torch.linspace(0, 1, n), torch.ones(tail)])
+ if args.sweep: # the live lead-in and tail orbit too, --live-speed times slower than the frozen frames
+ w = torch.tensor([args.live_speed] * (fz - args.start) + [1.0] * n + [args.live_speed] * tail)
+ ramp = torch.cumsum(w, 0) - w[0]
+ ramp = ramp / ramp[-1]
+else:
+ tmap = list(range(args.start, args.start + NUM_FRAMES))
+ # --bounce/--swing shape a 0->1 ramp. on the constant `ones` ramp they collapse to
+ # identically zero (cos 2pi = 1, sin 2pi = 0) and the camera never moves at all, so
+ # they imply the linear base ramp -- there is no useful reading of the other combination.
+ ramp = torch.linspace(0, 1, NUM_FRAMES) if args.sweep or args.bounce or args.swing else torch.ones(NUM_FRAMES)
+if args.ease:
+ ramp = (1 - torch.cos(math.pi * ramp)) / 2
+if args.bounce:
+ ramp = (1 - torch.cos(2 * math.pi * ramp)) / 2
+if args.swing:
+ ramp = torch.sin(2 * math.pi * ramp)
+if args.fast_back > 1: # piecewise-linear time->angle map: speed v on the outer quarters, K*v on the middle half
+ K, v = args.fast_back, 0.5 * (1 + 1 / args.fast_back)
+ t1 = 0.25 / v
+ ramp = torch.where(ramp < t1, v * ramp, torch.where(ramp < 1 - t1, 0.25 + K * v * (ramp - t1), 0.75 + v * (ramp - 1 + t1)))
+pf = tmap.index(fz) if args.freeze else 0 # the frame whose depth places the pivot
+c = av.open(args.video)
+frames = np.stack([f.to_ndarray(format="rgb24") for i, f in enumerate(c.decode(video=0)) if tmap[0] <= i <= tmap[-1]])
+c.close()
+assert len(frames) == tmap[-1] - tmap[0] + 1, f"decoded {len(frames)} frames from {tmap[0]}, need {tmap[-1] - tmap[0] + 1}"
+frames = torch.from_numpy(frames).to(device)
+h, w = frames.shape[1:3]
+s = FULL / max(h, w)
+ch, cw = round(h * s), round(w * s)
+ox, oy = (FULL - cw) // 2, (FULL - ch) // 2
+full = torch.zeros(len(frames), FULL, FULL, 3, dtype=torch.uint8, device=device)
+full[:, oy : oy + ch, ox : ox + cw] = resize_u8(frames, (ch, cw))
+del frames
+
+# The 768-class canvas nearest the clip's aspect, and a crop box of exactly that aspect inside the content
+# (`crop_box`'s construction, centred instead of drawn): the resize factor `f` stays isotropic, as in training.
+canvas, cond_canvas = bucket(w, h) # `` stays at the 480 class whatever the target is, as in training
+if args.canvas:
+ canvas = tuple(int(v) for v in args.canvas.split("x"))
+a = canvas[0] / canvas[1]
+bw, bh = (cw, round(cw / a)) if cw / ch <= a else (round(ch * a), ch)
+box = (ox + (cw - bw) // 2, oy + (ch - bh) // 2, bw, bh, canvas[0] / bw)
+x0, y0, bw, bh, _ = box
+print(f"{w}x{h} -> content {cw}x{ch} in {FULL}^2, box {box[:4]}, canvas {canvas}, cond {cond_canvas}", flush=True)
+
+# --- geometry: one solo pass, then the authored second camera in the same gauge ----------------------
+geometry = vggt(args.vggt, args.vggt_repo, device)
+t0 = time.time()
+S = reconstruct(geometry, to_input(full))
+del geometry
+idx = torch.tensor(tmap, device=device) - tmap[0]
+S = {k: v[idx] for k, v in S.items()}
+full = full[idx]
+if args.follow: # keep the clip's per-frame cameras, then pin every frame's geometry to the first
+ c2w_f, intr_f = S["c2w"].clone(), S["intr"].clone()
+ if args.smooth: # VGGT poses every frame independently, so the raw path jitters -- Gaussian low-pass it
+ n = len(c2w_f)
+ k = min(int(3 * args.smooth), n - 1) # point-reflect the ends (x[-j] = 2x[0] - x[j]): a plain
+ pad = lambda v: torch.cat([2 * v[:1] - v[1:k + 1].flip(0), v, 2 * v[-1:] - v[-k - 1:-1].flip(0)])
+ ts = torch.arange(n + 2 * k, device=device, dtype=torch.float32) # truncated window would pull the
+ w = torch.exp(-0.5 * ((ts[k:k + n, None] - ts[None, :]) / args.smooth) ** 2) # endpoints inward and
+ w = w / w.sum(1, keepdim=True) # eat 7% of the travel at sigma 8; reflection keeps the end velocity
+ sm = lambda v: torch.einsum("ij,jab->iab", w, pad(v))
+ jit = float((c2w_f[:, :3, 3] - sm(c2w_f)[:, :3, 3]).norm(dim=1).mean())
+ c2w_f, intr_f = sm(c2w_f), sm(intr_f)
+ U, _, Vh = torch.linalg.svd(c2w_f[:, :3, :3]) # blurring leaves R off SO(3); project it back
+ U[:, :, 2] *= torch.linalg.det(U @ Vh)[:, None] # never let the fit flip handedness
+ c2w_f[:, :3, :3], c2w_f[:, 3] = U @ Vh, torch.tensor([0.0, 0.0, 0.0, 1.0], device=device)
+ print(f"smoothed follow path, sigma {args.smooth} frames, removed {jit:.4f} mean jitter", flush=True)
+ z = [0] * NUM_FRAMES
+ S = {k: v[z] for k, v in S.items()}
+ full = full[z]
+if args.pivot and args.pivot != "none": # median depth in a +-5% window around the picked point, in VGGT's 512 grid
+ fx, fy = map(float, args.pivot.split(","))
+ r = RES / FULL
+ px, py, rw, rh = (x0 + fx * bw) * r, (y0 + fy * bh) * r, 0.05 * bw * r, 0.05 * bh * r
+ win = (slice(round(py - rh), round(py + rh)), slice(round(px - rw), round(px + rw)))
+ zm = float(S["depth"][pf][win][S["keep"][pf][win]].median())
+else:
+ zm = float(S["depth"][pf][S["keep"][pf]].median())
+piv = torch.tensor([0.0, 0.0, zm], device=device)
+if args.pivot and args.pivot != "none" and args.pivot_lock: # unproject the picked pixel; orbit about it so it holds its screen position
+ K = S["intr"][pf]
+ piv = torch.tensor([(px - float(K[0, 2])) / float(K[0, 0]) * zm, (py - float(K[1, 2])) / float(K[1, 1]) * zm, zm], device=device)
+ print(f"pivot locked at {piv.tolist()}", flush=True)
+piv_to = piv
+if args.pivot_to: # a second picked pixel; the aim target slides from `piv` to it along the ramp
+ gx, gy = map(float, args.pivot_to.split(","))
+ g = RES / FULL
+ qx, qy, qw, qh = (x0 + gx * bw) * g, (y0 + gy * bh) * g, 0.05 * bw * g, 0.05 * bh * g
+ wn = (slice(round(qy - qh), round(qy + qh)), slice(round(qx - qw), round(qx + qw)))
+ zt = float(S["depth"][pf][wn][S["keep"][pf][wn]].median())
+ K = S["intr"][pf]
+ piv_to = torch.tensor([(qx - float(K[0, 2])) / float(K[0, 0]) * zt, (qy - float(K[1, 2])) / float(K[1, 1]) * zt, zt], device=device)
+ print(f"reframe target at {piv_to.tolist()}", flush=True)
+c2w, intr_t = (c2w_f, intr_f) if args.follow else (S["c2w"].clone(), S["intr"].clone())
+for ti in range(0 if args.follow else NUM_FRAMES):
+ th = math.radians(args.yaw_from + (args.yaw - args.yaw_from) * float(ramp[ti]))
+ r = 1 + (args.dolly - 1) * float(ramp[ti])
+ R = torch.tensor([[math.cos(th), 0, math.sin(th)], [0, 1, 0], [-math.sin(th), 0, math.cos(th)]], device=device)
+ delta = torch.eye(4, device=device)
+ delta[:3, :3] = R
+ # orbit about `piv`: sit at r*|piv| from it along the rotated line of sight, then truck/boom in the rotated frame
+ delta[:3, 3] = piv - R @ (r * piv) - R @ torch.tensor([-args.truck * zm * float(ramp[ti]), args.boom * zm * float(ramp[ti]), 0.0], device=device)
+ if args.aim: # re-point at the pivot: boom/truck reframe the shot instead of sliding the subject out of frame
+ a = piv / piv.norm()
+ b = piv + (piv_to - piv) * float(ramp[ti]) - delta[:3, 3]
+ b = b / b.norm()
+ v, c = torch.cross(a, b, dim=0), float(a @ b)
+ sn = float(v.norm())
+ K = torch.zeros(3, 3, device=device)
+ K[0, 1], K[0, 2], K[1, 0], K[1, 2], K[2, 0], K[2, 1] = -v[2], v[1], v[2], -v[0], -v[1], v[0]
+ delta[:3, :3] = torch.eye(3, device=device) + K + K @ K * ((1 - c) / sn ** 2) if sn > 1e-8 else torch.eye(3, device=device)
+ c2w[ti] = S["c2w"][ti] @ delta
+ f = 1 + (args.zoom - 1) * float(ramp[ti]) if args.zoom else r
+ intr_t[ti, 0, 0] *= f
+ intr_t[ti, 1, 1] *= f
+if args.cull: # per frame: unproject the RES-grid depth, normal from finite differences, oriented toward the source camera
+ yy, xx = torch.meshgrid(torch.arange(RES, device=device), torch.arange(RES, device=device), indexing="ij")
+ uv1 = torch.stack([xx, yy, torch.ones_like(xx)], -1).float().reshape(-1, 3)
+ for ti in range(NUM_FRAMES):
+ Xc = (uv1 @ torch.linalg.inv(S["intr"][ti]).T).reshape(RES, RES, 3) * S["depth"][ti][..., None]
+ X = Xc @ S["c2w"][ti][:3, :3].T + S["c2w"][ti][:3, 3]
+ n = torch.cross(torch.roll(X, -1, 1) - X, torch.roll(X, -1, 0) - X, dim=-1)
+ n = n * torch.sign((n * (S["c2w"][ti][:3, 3] - X)).sum(-1, keepdim=True))
+ S["keep"][ti] &= ((c2w[ti][:3, 3] - X) * n).sum(-1) > 0
+ print(f"cull: keep fraction per frame {S['keep'].float().mean((1, 2)).min():.2f}..{S['keep'].float().mean((1, 2)).max():.2f}", flush=True)
+w2c = torch.linalg.inv(c2w)
+render, cov = warp(S, w2c, intr_t, full, box, canvas)
+yy, xx = torch.meshgrid(torch.arange(RES, device=device), torch.arange(RES, device=device), indexing="ij")
+g1 = torch.stack([xx, yy, torch.ones_like(xx)], -1).float().reshape(-1, 3)
+near, behind, coll, ahead = [], [], [], []
+for ti in range(NUM_FRAMES): # fly-through gauge: how much of the scene ends up near, behind, or (collide) within a 0.05-pivot-depth ball of the moved camera
+ X = ((g1 @ torch.linalg.inv(S["intr"][ti]).T).reshape(RES, RES, 3) * S["depth"][ti][..., None]) @ S["c2w"][ti][:3, :3].T + S["c2w"][ti][:3, 3]
+ zd = (X - c2w[ti][:3, 3]) @ c2w[ti][:3, 2]
+ near.append(float((zd[S["keep"][ti]] < 0.1 * zm).float().mean()))
+ behind.append(float((zd[S["keep"][ti]] < 0).float().mean()))
+ coll.append(float(((X - c2w[ti][:3, 3]).norm(dim=-1)[S["keep"][ti]] < 0.05 * zm).float().mean()))
+ cb = S["keep"][ti].clone(); cb[: RES // 4] = cb[-(RES // 4):] = False; cb[:, : RES // 4] = cb[:, -(RES // 4):] = False # central half of the source frame: the subject, not the floor
+ ahead.append(float(torch.quantile(zd[cb], 0.05)) / zm if cb.any() else 9.0)
+print(f"fly-through gauge: scene within 0.1 pivot-depths of the moved camera, per-frame max {max(near):.3f} at frame {near.index(max(near))}; "
+ f"behind the camera max {max(behind):.3f} at frame {behind.index(max(behind))}; "
+ f"collide (within a 0.05-pivot-depth ball) max {max(coll):.4f} at frame {coll.index(max(coll))}; "
+ f"central-subject 5th-pct depth ahead of the moved camera min {min(ahead):+.3f} pivot-depths at frame {ahead.index(min(ahead))}", flush=True)
+print(f"pivot depth {zm:.3f}, camera moved {float((c2w[-1, :3, 3] - S['c2w'][-1, :3, 3]).norm()) / zm:.3f} pivot-depths "
+ f"by the last frame, coverage {float(cov.float().mean()):.3f}, geometry in {time.time() - t0:.0f}s", flush=True)
+if args.gauge_only:
+ sys.exit(0)
+
+# --- encode exactly as `build` does; the target latent is a placeholder that only sets the layout --------
+render = resize_u8(render, cond_canvas[::-1])
+source = resize_u8(full[:, y0 : y0 + bh, x0 : x0 + bw], canvas[::-1])
+cond = resize_u8(full[:, y0 : y0 + bh, x0 : x0 + bw], cond_canvas[::-1])
+del full
+vae = AutoencoderKLMiniMaxH3.from_pretrained(args.model_dir, subfolder="vae").to(device).eval()
+d = {"cond": encode_video(vae, cond)[0], "render": encode_video(vae, render)[0], "target": encode_video(vae, source)[1]}
+
+embed = torch.load(f"{ASSETS}/fixed_embed_{NUM_FRAMES}.pt", weights_only=False)
+audio_x0 = torch.load(f"{ASSETS}/silence_audio_{NUM_FRAMES}.pt", weights_only=True)["audio_x0"].float()
+batch = pack(d["cond"], d["render"], d["target"], embed["prompt_embeds"][0], embed["text_token_tags"], audio_x0)
+
+# --- denoise ----------------------------------------------------------------------------------------
+transformer = MiniMaxH3Transformer3DModel.from_pretrained(args.ckpt, torch_dtype=torch.bfloat16)
+if not args.no_lora:
+ # `prefix=None` + the safetensors name, or the loader looks for a `.bin` / filters for `transformer.` keys and
+ # silently loads nothing. The assert is the guard against that silence.
+ transformer.load_lora_adapter(args.lora, weight_name="pytorch_lora_weights.safetensors", prefix=None)
+ assert any("lora_" in n for n, _ in transformer.named_parameters()), "no LoRA weights landed"
+transformer.set_attention_backend(args.attn_backend)
+transformer.to(device).eval()
+t0 = time.time()
+torch.cuda.reset_peak_memory_stats()
+rows = denoise(transformer, batch, args.steps, args.flow_shift, device)
+print(f"denoised in {time.time() - t0:.0f}s, peak {torch.cuda.max_memory_allocated() / 2**30:.1f} GiB", flush=True)
+del transformer
+out = decode_video(vae, rows, d["target"].shape[1:])
+
+# --- write ----------------------------------------------------------------------------------------
+hw = canvas[::-1]
+for name, fr in ("out", out), ("render", render.cpu()), ("source", source.cpu()):
+ write_mp4(fr, fps=int(FPS), output_path=f"{args.out}/{name}.mp4")
+write_mp4(torch.cat([source.cpu(), resize_u8(render.cpu(), hw), out], 2), fps=int(FPS), output_path=f"{args.out}/grid.mp4")
+Image.fromarray(out[-1].numpy()).save(f"{args.out}/last.png") # the next link of an autoregressive orbit
+if not args.freeze: # a frozen window has no soundtrack that lines up
+ subprocess.run(["ffmpeg", "-v", "error", "-y", "-i", f"{args.out}/out.mp4", "-ss", f"{args.start / FPS:.4f}",
+ "-t", f"{NUM_FRAMES / FPS:.4f}", "-i", args.video, "-map", "0:v", "-map", "1:a?", "-c:v", "copy",
+ "-c:a", "aac", "-shortest", f"{args.out}/out_audio.mp4"], check=True)
+# poses last: the mp4s are already on disk, so nothing here can cost a render
+_x0, _y0, _bw, _bh, _sx = box # intr_* live on the RES grid of the FULL^2 letterbox; *_px are in out.mp4 pixels
+_M = np.array([[FULL / RES * _sx, 0, -_x0 * _sx], [0, FULL / RES * canvas[1] / _bh, -_y0 * canvas[1] / _bh], [0, 0, 1]])
+np.savez(f"{args.out}/cams.npz", c2w_src=S["c2w"].cpu().numpy(), c2w_dst=c2w.cpu().numpy(),
+ intr_src=S["intr"].cpu().numpy(), intr_dst=intr_t.cpu().numpy(),
+ intr_src_px=_M @ S["intr"].cpu().numpy(), intr_dst_px=_M @ intr_t.cpu().numpy(),
+ piv=piv.cpu().numpy(), piv_to=piv_to.cpu().numpy(), zm=float(zm),
+ box=np.asarray(box), canvas=np.asarray(canvas), fps=float(FPS), argv=" ".join(sys.argv[1:]))
+print(f"wrote {args.out}/{{out,render,source,grid}}.mp4 + last.png + cams.npz" + ("" if args.freeze else " + out_audio.mp4"))
diff --git a/recam/__init__.py b/recam/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..42711abfb51e6462ea8c5a7167e1839e071be003
--- /dev/null
+++ b/recam/__init__.py
@@ -0,0 +1,2 @@
+# Copyright 2026 Viggle AI. Licensed under the Apache License, Version 2.0 (see LICENSE-CODE).
+# SPDX-License-Identifier: Apache-2.0
diff --git a/recam/geometry.py b/recam/geometry.py
new file mode 100644
index 0000000000000000000000000000000000000000..578f3862e783158e0dff78feddc3c5f64da130c2
--- /dev/null
+++ b/recam/geometry.py
@@ -0,0 +1,168 @@
+# Copyright 2026 Viggle AI. Licensed under the Apache License, Version 2.0 (see LICENSE-CODE).
+# SPDX-License-Identifier: Apache-2.0
+"""Geometry: one solo VGGT-Omega pass per clip, then the clip's point cloud rendered from any camera.
+
+ frames [F,H,W,3] u8 --letterbox--> [F,FULL,FULL,3] --to_input--> [F,3,RES,RES] --reconstruct--> S
+ S + an authored camera path --warp--> [F,h,w,3] u8 render with mid-grey holes, + coverage
+
+`S` is per-frame depth / confidence-pruned `keep` / extrinsics / intrinsics in VGGT's 512 px frame; every
+frame is reconstructed on its own (the model sees the whole clip, but no target footage exists at
+inference), and cameras are authored in the *source's* gauge: the source camera of the window's first
+frame is the world origin and one unit is the median depth around the picture centre (`gauge`).
+"""
+
+import os
+import sys
+
+import torch
+import torch.nn.functional as F
+import torchvision.transforms.v2.functional as TF
+
+FULL = 1280 # side of the square the source is letterboxed into (the training corpus's native side)
+RES = 512 # VGGT input side
+CONF_PCT, EDGE_RTOL = 2.0, 0.30 # drop the 2 % least confident points and every 3x3 depth edge wider than 30 %
+HOLE = 128 # uncovered pixels: mid grey. There is no mask channel; the prompt says grey is a hole.
+NUM_FRAMES = 73
+LENGTHS = (73, 90, 107, 124, 141, 158, 175, 243) # 17k+5, the lengths `assets/` has a prompt embed for
+
+
+def vggt(ckpt=None, repo=None, device="cuda"):
+ """Load VGGT-Omega (1B, 512). Not redistributed here -- see README: clone facebookresearch/vggt-omega and
+ download `vggt_omega_1b_512.pt` from the gated `facebook/VGGT-Omega`. Defaults: `$VGGT_OMEGA_DIR`,
+ `$VGGT_OMEGA_CKPT`."""
+ repo = repo or os.environ.get("VGGT_OMEGA_DIR")
+ ckpt = ckpt or os.environ.get("VGGT_OMEGA_CKPT") or (repo and f"{repo}/checkpoints/vggt_omega_1b_512.pt")
+ if not ckpt:
+ raise RuntimeError("VGGT-Omega not found: set $VGGT_OMEGA_DIR (and $VGGT_OMEGA_CKPT if the .pt lives elsewhere) "
+ "or pass --vggt-repo / --vggt; see README, Install")
+ if repo:
+ sys.path.insert(0, repo)
+ from vggt_omega.models import VGGTOmega
+
+ model = VGGTOmega().eval()
+ model.load_state_dict(torch.load(ckpt, map_location="cpu"))
+ return model.to(device)
+
+
+def reconstruct(model, imgs):
+ """[N,3,512,512] in [0,1] -> dict(extr, intr, depth, keep, c2w). `keep` drops depth edges and low confidence."""
+ from vggt_omega.utils.pose_enc import encoding_to_camera
+
+ with torch.inference_mode():
+ pred = model(imgs)
+ extr, intr = encoding_to_camera(pred["pose_enc"], (RES, RES))
+ depth = pred["depth"][0, ..., 0].float()
+ conf = pred["depth_conf"][0].float().clone()
+ mx = F.max_pool2d(depth[None], 3, 1, 1)[0]
+ mn = -F.max_pool2d(-depth[None], 3, 1, 1)[0]
+ conf[(mx - mn) / depth.abs().clamp(min=1e-6) > EDGE_RTOL] = 0.0
+ keep = torch.isfinite(depth) & torch.isfinite(conf) & (conf > 1e-5)
+ q = torch.stack([torch.quantile(conf[i][keep[i]], CONF_PCT / 100) if keep[i].any()
+ else conf.new_zeros(()) for i in range(len(conf))])
+ keep &= conf >= q[:, None, None]
+ w2c = torch.eye(4, device=depth.device).repeat(len(depth), 1, 1)
+ w2c[:, :3, :4] = extr[0].float()
+ return dict(extr=extr[0].float().clone(), intr=intr[0].float().clone(), depth=depth.clone(),
+ keep=keep.clone(), c2w=torch.linalg.inv(w2c))
+
+
+def unproject(depth, extr, intr):
+ n, h, w = depth.shape
+ yy, xx = torch.meshgrid(torch.arange(h, device=depth.device, dtype=torch.float32),
+ torch.arange(w, device=depth.device, dtype=torch.float32), indexing="ij")
+ fx, fy = intr[:, 0, 0][:, None, None], intr[:, 1, 1][:, None, None]
+ cx, cy = intr[:, 0, 2][:, None, None], intr[:, 1, 2][:, None, None]
+ cam = torch.stack([(xx - cx) / fx * depth, (yy - cy) / fy * depth, depth], -1)
+ return torch.einsum("sij,shwj->shwi", extr[:, :3, :3].transpose(1, 2),
+ cam - extr[:, :3, 3][:, None, None, :])
+
+
+def upsample(depth, keep, n=FULL):
+ """512 depth/keep -> n x n. Bilinear depth; a hi-res pixel survives only where all parents did,
+ which kills bilinear's flying pixels across a depth discontinuity."""
+ d = F.interpolate(depth[:, None], size=(n, n), mode="bilinear", align_corners=False)[:, 0]
+ k = F.interpolate(keep[:, None].float(), size=(n, n), mode="bilinear", align_corners=False)[:, 0] > 0.999
+ return d, k
+
+
+def scale_k(K, f):
+ """`K` for an image resized by `f` under the pixel-centre convention every resampler here uses
+ (`x_hi = f*(x_lo + 0.5) - 0.5`), so the principal point picks up `0.5*(f-1)` on top of the scaling."""
+ out = K * f
+ out[..., 2, 2] = 1.0
+ out[..., :2, 2] += 0.5 * (f - 1)
+ return out
+
+
+def canvas_k(K, box, f):
+ """`K` (VGGT 512-space, `[...,3,3]`) -> the crop box `box` resized by `f`, i.e. canvas pixels."""
+ x0, y0 = box[:2]
+ out = scale_k(K, FULL / RES)
+ out[..., 0, 2] -= x0
+ out[..., 1, 2] -= y0
+ return scale_k(out, f)
+
+
+def render_hw(P, C, extr, intr, H, W, splat=1):
+ """Z-buffer point splat (3x3 per point). Returns the image and the covered pixels."""
+ cam = P @ extr[:3, :3].T + extr[:3, 3]
+ m = cam[:, 2] > 1e-6
+ cam, C = cam[m], C[m]
+ z = cam[:, 2]
+ u = cam[:, 0] / z * intr[0, 0] + intr[0, 2]
+ v = cam[:, 1] / z * intr[1, 1] + intr[1, 2]
+
+ offs = [(dx, dy) for dy in (-splat, 0, splat) for dx in (-splat, 0, splat)]
+ x = torch.cat([(u + dx).round() for dx, _ in offs]).long()
+ y = torch.cat([(v + dy).round() for _, dy in offs]).long()
+ z = z.repeat(len(offs))
+ C = C.repeat(len(offs), 1)
+ k = (x >= 0) & (x < W) & (y >= 0) & (y < H)
+ idx, z, C = (y[k] * W + x[k]), z[k], C[k]
+
+ zbuf = torch.full((H * W,), float("inf"), device=P.device)
+ zbuf.scatter_reduce_(0, idx, z, "amin", include_self=True)
+ win = z == zbuf[idx]
+ img = torch.full((H * W, 3), HOLE, dtype=torch.uint8, device=P.device)
+ img[idx[win]] = C[win]
+ cov = torch.zeros(H * W, dtype=torch.bool, device=P.device)
+ cov[idx] = True
+ return img.view(H, W, 3), cov.view(H, W)
+
+
+def warp(S, w2c, intr_t, src_full, box, canvas):
+ """The source clip's per-frame point cloud, seen from the target camera `w2c [F,4,4]` with intrinsics
+ `intr_t [F,3,3]` (VGGT 512-space). `box = (x0, y0, w, h, f)` is the crop box in the letterboxed frame and
+ its resize factor to `canvas = (w, h)`. One frame at a time: a 1280x1280 unproject is 19 MB of points."""
+ x0, y0, cw, ch, f = box
+ w, h = canvas
+ imgs, covs = [], []
+ for ti in range(len(src_full)):
+ n = src_full.shape[1]
+ d, k = upsample(S["depth"][ti : ti + 1], S["keep"][ti : ti + 1], n)
+ Kf = scale_k(S["intr"][ti], FULL / RES)
+ P = unproject(d, S["extr"][ti : ti + 1], Kf[None])[0][y0 : y0 + ch, x0 : x0 + cw]
+ kb = k[0, y0 : y0 + ch, x0 : x0 + cw]
+ Kc = canvas_k(intr_t[ti], box, f)
+ img, cov = render_hw(P[kb], src_full[ti, y0 : y0 + ch, x0 : x0 + cw][kb], w2c[ti, :3], Kc, h, w)
+ imgs.append(img)
+ covs.append(cov)
+ return torch.stack(imgs), torch.stack(covs)
+
+
+def resize_u8(x, size, mode=TF.InterpolationMode.BILINEAR, chunk=16):
+ """[F,H,W,3] uint8 -> [F,size[0],size[1],3] uint8, antialiased, chunked to bound memory."""
+ out = []
+ for i in range(0, len(x), chunk):
+ y = TF.resize(x[i : i + chunk].permute(0, 3, 1, 2).float(), list(size), mode, antialias=True)
+ out.append(y.clamp_(0, 255).round_().to(torch.uint8).permute(0, 2, 3, 1))
+ return torch.cat(out)
+
+
+def to_input(x, chunk=16):
+ """[F,FULL,FULL,3] uint8 -> [F,3,RES,RES] float in [0,1]. Bicubic, matching VGGT's own preprocessing."""
+ out = []
+ for i in range(0, len(x), chunk):
+ y = x[i : i + chunk].permute(0, 3, 1, 2).float().div(255)
+ out.append(TF.resize(y, [RES, RES], TF.InterpolationMode.BICUBIC, antialias=True).clamp_(0, 1))
+ return torch.cat(out)
diff --git a/recam/h3.py b/recam/h3.py
new file mode 100644
index 0000000000000000000000000000000000000000..93c98138d76e03c0112b9cca205be26b678536e0
--- /dev/null
+++ b/recam/h3.py
@@ -0,0 +1,140 @@
+# Copyright 2026 Viggle AI. Licensed under the Apache License, Version 2.0 (see LICENSE-CODE).
+# SPDX-License-Identifier: Apache-2.0
+"""The MiniMax-H3 side: VAE encode, the packed `ref2va` sequence, and the canvas ladders.
+
+The render is a *second video reference*: `` is the source clip, `` the point-cloud
+render, both at the 480 class, packed as condition rows by the pipeline's own
+`build_ref2va_packed_sequence` after the frozen text rows, then the noised target at the 768 class.
+Tokens, not channels -- nothing about the transformer is touched, so a checkpoint is a plain
+`transformer/` directory and the DMD student is an ordinary PEFT LoRA on it.
+"""
+
+import math
+
+import torch
+from diffusers import MiniMaxH3Scheduler
+from diffusers.modular_pipelines.minimax_h3.before_denoise import (
+ MiniMaxH3Ref2VAPrepareLayoutStep, MiniMaxH3SetTimestepsStep, patchify_video_latents,
+)
+
+# Canvases, one per aspect bucket; entry `i` is the same aspect in every class (to within 1.3 %), which is what
+# lets ``/`` sit at the 480 class under a 768-class target: the rotary grid is normalised by
+# sqrt(area), so the condition block spans the same rotary rectangle as the target it conditions.
+LADDERS = {
+ 480: [(416, 960), (448, 896), (480, 832), (544, 736), (640, 640), (736, 544), (832, 480), (896, 448), (960, 416)],
+ 768: [(672, 1536), (704, 1408), (768, 1344), (864, 1184), (1024, 1024), (1184, 864), (1344, 768), (1408, 704), (1536, 672)],
+}
+TARGET_CLASS, COND_CLASS = 768, 480
+
+PATCH_SIZE = (1, 2, 2)
+AUDIO_CHANNELS = 2
+VIDEO_TAG, TEXT_TAG, AUDIO_TAG = 0, 1, 2
+KEYFRAME_NOISE_AUG = 0.999 # the pipeline's noise level on condition rows
+VIDEO_SHIFT = 12.0 # scheduler/scheduler_config.json of MiniMax-H3
+AUDIO_SHIFT = 3.0 # audio_scheduler/scheduler_config.json
+PIXEL_MEAN = (0.485, 0.456, 0.406)
+PIXEL_STD = (0.229, 0.224, 0.225)
+ENCODE_SEED = 42
+FPS = 24.0 # the frame rate the frozen prompt declares; the model has no other notion of time
+
+
+def bucket(w, h):
+ """`(target canvas, condition canvas)` for a `w x h` source: the ladder entry nearest in log-aspect."""
+ i = min(range(len(LADDERS[TARGET_CLASS])),
+ key=lambda i: abs(math.log(LADDERS[TARGET_CLASS][i][0] / LADDERS[TARGET_CLASS][i][1] * h / w)))
+ return LADDERS[TARGET_CLASS][i], LADDERS[COND_CLASS][i]
+
+
+class _Reference:
+ """All `build_ref2va_packed_sequence` reads off a reference is its modality."""
+
+ def __init__(self, kind):
+ self.kind, self.has_audio = kind, False
+
+
+def encode_video(vae, video):
+ """[F,H,W,3] uint8 -> `(anchor, target)` normalised latents `[1,C,T,h,w]` from one `vae.encode`: the
+ anchor is the pipeline's seed-42 fp16-rounded draw (what a condition block gets), the target a fresh draw."""
+ latents_mean = torch.tensor(vae.config.latents_mean).view(1, -1, 1, 1, 1)
+ latents_std = torch.tensor(vae.config.latents_std).view(1, -1, 1, 1, 1)
+ mean = torch.tensor(PIXEL_MEAN, device=video.device).view(1, -1, 1, 1, 1)
+ std = torch.tensor(PIXEL_STD, device=video.device).view(1, -1, 1, 1, 1)
+ pixels = video.permute(3, 0, 1, 2)[None].to(torch.float32).div(255.0)
+ posterior = vae.encode((pixels - mean) / std, return_dict=False)[0]
+ anchor = posterior.sample(generator=torch.Generator().manual_seed(ENCODE_SEED)).to(torch.float16).float().cpu()
+ return (anchor - latents_mean) / latents_std, (posterior.sample().float().cpu() - latents_mean) / latents_std
+
+
+def decode_video(vae, rows, shape):
+ """Packed target rows -> [F,H,W,3] uint8. `shape` is the target latent's `(C, T, h, w)`."""
+ C, T, H, W = shape
+ pt, ph, pw = PATCH_SIZE
+ dev = rows.device
+ x = rows.reshape(1, T // pt, H // ph, W // pw, C, pt, ph, pw).permute(0, 4, 1, 5, 2, 6, 3, 7).reshape(1, C, T, H, W)
+ x = x * torch.tensor(vae.config.latents_std, device=dev).view(1, -1, 1, 1, 1) \
+ + torch.tensor(vae.config.latents_mean, device=dev).view(1, -1, 1, 1, 1)
+ with torch.autocast("cuda", dtype=torch.float16):
+ video = vae.decode(x, return_dict=False)[0]
+ video = video.float() * torch.tensor(PIXEL_STD, device=dev).view(1, -1, 1, 1, 1) \
+ + torch.tensor(PIXEL_MEAN, device=dev).view(1, -1, 1, 1, 1)
+ return (video.clamp(0, 1)[0].permute(1, 2, 3, 0) * 255).round().to(torch.uint8).cpu()
+
+
+def pack(cond, render, target, prompt_embeds, text_token_tags, audio_x0):
+ """`[text | = cond | = render | target]` as the transformer's packed inputs.
+
+ The layout, rotary geometry and modality tags come from the pipeline's own builder. Condition rows carry
+ the pipeline's `KEYFRAME_NOISE_AUG` noise augmentation; the target rows (and the audio rows) start as
+ pure noise. Returns the dict of tensors the denoise loop needs plus `num_condition_video_rows` /
+ `num_condition_audio_rows`.
+ """
+ refs = [cond.float(), render.float()]
+ position_ids, token_tags, video_indices, audio_indices, text_indices, n_cond_video, n_cond_audio = \
+ MiniMaxH3Ref2VAPrepareLayoutStep.build_ref2va_packed_sequence(
+ text_token_tags, [_Reference("video"), _Reference("video")], refs, [],
+ target.shape[2], target.shape[3], target.shape[4],
+ audio_x0.shape[0] // AUDIO_CHANNELS,
+ PATCH_SIZE, AUDIO_CHANNELS, AUDIO_TAG, VIDEO_TAG,
+ )
+ cond_rows = torch.cat([
+ patchify_video_latents(KEYFRAME_NOISE_AUG * x + (1.0 - KEYFRAME_NOISE_AUG) * torch.randn_like(x), PATCH_SIZE)
+ for x in refs
+ ])
+ target_rows = torch.randn_like(patchify_video_latents(target.float(), PATCH_SIZE))
+ return {
+ "hidden_states": torch.cat([cond_rows, target_rows]),
+ "audio_hidden_states": torch.randn_like(audio_x0),
+ "encoder_hidden_states": prompt_embeds,
+ "token_tags": token_tags,
+ "position_ids": position_ids,
+ "video_indices": video_indices,
+ "audio_indices": audio_indices,
+ "text_indices": text_indices,
+ "num_condition_video_rows": n_cond_video,
+ "num_condition_audio_rows": n_cond_audio,
+ }
+
+
+def denoise(transformer, batch, steps, flow_shift, device, on_step=None):
+ """Walk the scheduler over the target rows in place. `--steps 4 --flow-shift 3` is the DMD student's grid
+ (3 forwards); the teacher wants `--steps 50 --flow-shift 12`."""
+ batch = {k: v.to(device) if torch.is_tensor(v) else v for k, v in batch.items()}
+ n_cond, n_cond_audio = batch["num_condition_video_rows"], batch["num_condition_audio_rows"]
+ latents, audio = batch["hidden_states"], batch["audio_hidden_states"]
+ sch, asch = MiniMaxH3Scheduler(shift=flow_shift), MiniMaxH3Scheduler(shift=AUDIO_SHIFT)
+ sch.set_timesteps(steps, device)
+ asch.set_timesteps(steps, device)
+ layout = {k: batch[k] for k in ("token_tags", "position_ids", "video_indices", "audio_indices", "text_indices")}
+ prompt = batch["encoder_hidden_states"].to(torch.bfloat16)[None]
+ for i, (t, at) in enumerate(zip(sch.timesteps, asch.timesteps)):
+ if on_step:
+ on_step(i, len(sch.timesteps))
+ timestep, ti = MiniMaxH3SetTimestepsStep.build_row_timesteps(
+ batch["video_indices"], batch["audio_indices"], n_cond, n_cond_audio, batch["text_indices"].numel(),
+ float(t), float(at), max(float(t), KEYFRAME_NOISE_AUG), 1.0)
+ v, av = transformer(hidden_states=latents[None], audio_hidden_states=audio[None], encoder_hidden_states=prompt,
+ timestep=timestep.to(device), timestep_indices=ti.to(device), **layout, return_dict=False)
+ latents[n_cond:] = sch.step(v[0, n_cond:].float(), t, latents[n_cond:], return_dict=False)[0]
+ audio = asch.step(av[0].float(), at, audio, return_dict=False)[0]
+ return latents[n_cond:]
+
diff --git a/recam/path.py b/recam/path.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa9566f48690a2766a42de65a51a9406639e5317
--- /dev/null
+++ b/recam/path.py
@@ -0,0 +1,104 @@
+# Copyright 2026 Viggle AI. Licensed under the Apache License, Version 2.0 (see LICENSE-CODE).
+# SPDX-License-Identifier: Apache-2.0
+"""Keyframe camera paths for the demo service -- pure math, no models.
+
+A key is `{pos, look, src, t, ease?, focal?}`:
+ pos where the camera is, in the world frame W (the source camera of frame `start`: x right, y down,
+ z forward), in units of the pivot depth `zm`
+ look the 3D point the camera looks at, same frame and units
+ src which source frame this key shows (absolute frame index of the clip)
+ t which output frame this key lands on: the first key is frame 0, the last is frame `frames - 1`,
+ and they increase strictly in between
+ ease optional, eases the pose motion of the segment leaving this key (time stays linear)
+ focal optional focal multiplier, default 1
+
+Between keys `pos` and `look` run on a Catmull-Rom curve (cubic Hermite with finite-difference tangents,
+non-uniform in time), `src` and `focal` run linearly. The orientation is derived from `look - pos` with roll
+locked to zero -- the training corpus has no roll (p99 2.1 deg), so a rolled camera is genuinely out of
+distribution. Time never runs backwards: `src` must be non-decreasing. Bullet time is two keys with the same
+`src` at different `t`; a plain move is keys whose `src` advance one frame per output frame.
+"""
+import math
+
+import numpy as np
+
+UP = np.array([0.0, -1.0, 0.0]) # y is down in the camera frame
+
+
+def key_times(path, frames):
+ """Output frame index of every key."""
+ t = [int(k["t"]) for k in path]
+ assert len(t) >= 2 and t[0] == 0 and t[-1] == frames - 1 and all(b > a for a, b in zip(t, t[1:])), \
+ f"key output frames {t} must run from 0 to {frames - 1}, strictly increasing"
+ return t
+
+
+def hermite(tk, pk, t, ease):
+ """Catmull-Rom through (tk, pk[k]) evaluated at t. pk: (K, D). ease[k]: ease segment k."""
+ tk, pk = np.asarray(tk, float), np.asarray(pk, float)
+ K = len(tk)
+ d = np.diff(pk, axis=0) / np.diff(tk)[:, None] # chord slope of every segment
+ m = np.zeros_like(pk)
+ m[0], m[-1] = d[0], d[-1]
+ m[1:-1] = 0.5 * (d[:-1] + d[1:])
+ m[1:-1][d[:-1] * d[1:] <= 0] = 0 # Fritsch-Carlson: no overshoot, and a hold between equal keys stays exactly still
+ lim = 3 * np.minimum(np.abs(d[:-1]), np.abs(d[1:])) # ... and no tangent steeper than 3x the gentler chord, or a slow-then-fast pair dips backwards first
+ m[1:-1] = np.clip(m[1:-1], -lim, lim)
+ out = np.zeros((len(t), pk.shape[1]))
+ for i, x in enumerate(t):
+ k = min(int(np.searchsorted(tk, x, side="right")) - 1, K - 2)
+ h = tk[k + 1] - tk[k]
+ s = (x - tk[k]) / h
+ if ease[k]:
+ s = (1 - math.cos(math.pi * s)) / 2
+ h00, h10, h01, h11 = 2 * s**3 - 3 * s**2 + 1, s**3 - 2 * s**2 + s, -2 * s**3 + 3 * s**2, s**3 - s**2
+ out[i] = h00 * pk[k] + h10 * h * m[k] + h01 * pk[k + 1] + h11 * h * m[k + 1]
+ return out
+
+
+def look_at(pos, look, prev=None):
+ """c2w rotation (columns right, down, forward) looking from pos at look with zero roll."""
+ f = look - pos
+ n = np.linalg.norm(f)
+ if n < 1e-6:
+ return prev if prev is not None else np.eye(3)
+ f = f / n
+ r = np.cross(f, UP)
+ if np.linalg.norm(r) < 1e-6: # looking straight up or down: keep x as right
+ r = np.array([1.0, 0.0, 0.0])
+ r = r / np.linalg.norm(r)
+ d = np.cross(f, r)
+ return np.stack([r, d, f], 1)
+
+
+def plan_path(path, frames, zm):
+ """-> per-frame c2w in W (4x4, translation in scene units), per-frame source frame, per-frame focal,
+ per-segment source speed (source frames per output frame: 0 = frozen, 1 = real time)."""
+ tk = key_times(path, frames)
+ src = [int(k["src"]) for k in path]
+ assert all(b >= a for a, b in zip(src, src[1:])), f"source frames {src} run backwards"
+ t = np.arange(frames)
+ ease = [bool(k.get("ease", False)) for k in path]
+ pos = hermite(tk, [k["pos"] for k in path], t, ease) * zm
+ look = hermite(tk, [k["look"] for k in path], t, ease) * zm
+ tmap = np.rint(np.interp(t, tk, src)).astype(int).tolist()
+ focal = np.interp(t, tk, [float(k.get("focal", 1.0)) for k in path]).tolist()
+ c2w = np.tile(np.eye(4), (frames, 1, 1))
+ R = None
+ for i in range(frames):
+ R = look_at(pos[i], look[i], R)
+ c2w[i, :3, :3], c2w[i, :3, 3] = R, pos[i]
+ speed = [(src[k + 1] - src[k]) / (tk[k + 1] - tk[k]) for k in range(len(tk) - 1)]
+ return c2w, tmap, focal, speed
+
+
+def describe(c2w_W, piv_W, zm):
+ """The inverse: per-frame (pos, look) in path units from c2w in W. `look` is the point on the optical
+ axis at the pivot's depth, so a camera aimed at the pivot reports the pivot itself."""
+ out = []
+ for M in np.asarray(c2w_W):
+ p, f, r = M[:3, 3], M[:3, 2], M[:3, 0]
+ d = max(float((piv_W - p) @ f), 0.05 * zm)
+ roll = math.degrees(math.atan2(-float(r @ UP), math.hypot(r[0], r[2]))) # 0 for a level camera
+ out.append(dict(pos=(p / zm).round(4).tolist(), look=((p + f * d) / zm).round(4).tolist(), roll=round(roll, 2)))
+ return out
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bab7bc73ad9db16b107d2b7b16d5c3f29fc405f1
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,14 @@
+torch==2.9.1
+torchvision==0.24.1
+git+https://github.com/huggingface/diffusers@d6726f3
+transformers>=4.57
+safetensors>=0.7
+av==16.1.0
+numpy
+pillow
+# the demo service only
+fastapi
+uvicorn
+python-multipart
+# VGGT-Omega is NOT on this list: it is not pip-installable and its licence does not allow us to
+# redistribute it. See README.md, "Install", for the two environment variables that point at your copy.
diff --git a/service/app.py b/service/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..c6776baa759150290c55337c3908068e0bc609a4
--- /dev/null
+++ b/service/app.py
@@ -0,0 +1,544 @@
+# Copyright 2026 Viggle AI. Licensed under the Apache License, Version 2.0 (see LICENSE-CODE).
+# SPDX-License-Identifier: Apache-2.0
+"""The demo service: upload a clip -> geometry is reconstructed at once -> author a keyframe camera path in
+3D -> truthful warp preview -> render.
+
+One process, one GPU, everything resident (VGGT-Omega + VAE + teacher + the DMD student LoRA, ~77 GiB at boot).
+A warp of the whole trajectory takes 0.24 s, so every judgement the visitor makes is made on the real thing
+the model will be conditioned on -- downsampled to `cond_canvas`, the 480 class, not the output canvas.
+
+ CUDA_VISIBLE_DEVICES=0 python service/app.py --port 8412 # or service/run.sh
+
+See README.md, "Self-hosting the demo", for the endpoints and the measured budget.
+"""
+
+import argparse
+import hashlib
+import io
+import itertools
+import json
+import math
+import os
+import subprocess
+import sys
+import threading
+import time
+
+import av
+import numpy as np
+import torch
+import uvicorn
+from diffusers import AutoencoderKLMiniMaxH3, MiniMaxH3Transformer3DModel
+from diffusers.utils.export_utils import encode_video as write_mp4
+from fastapi import FastAPI, File, HTTPException, Request, UploadFile
+from fastapi.responses import FileResponse, HTMLResponse, JSONResponse, Response
+from PIL import Image
+
+HERE = os.path.dirname(os.path.abspath(__file__))
+ROOT = os.path.dirname(HERE)
+sys.path.insert(0, ROOT)
+from recam.geometry import FULL, RES, reconstruct, resize_u8, to_input, vggt, warp # noqa: E402
+from recam.h3 import FPS, bucket, decode_video, denoise, encode_video, pack # noqa: E402
+from recam.path import describe, look_at, plan_path # noqa: E402
+
+p = argparse.ArgumentParser()
+p.add_argument("--ckpt", default=f"{ROOT}/transformer", help="the finetuned transformer (a diffusers `transformer/` dir)")
+p.add_argument("--lora", default=f"{ROOT}/lora", help="the DMD student LoRA")
+p.add_argument("--model-dir", default="MiniMaxAI/MiniMax-H3", help="the base MiniMax-H3 repo or a local copy, for `vae/`")
+p.add_argument("--vggt", default=None, help="vggt_omega_1b_512.pt; default $VGGT_OMEGA_CKPT (see README)")
+p.add_argument("--vggt-repo", default=None, help="a checkout of facebookresearch/vggt-omega; default $VGGT_OMEGA_DIR")
+p.add_argument("--steps", type=int, default=4, help="the student's grid: 4 timesteps = 3 forwards")
+p.add_argument("--flow-shift", type=float, default=3.0)
+p.add_argument("--work", default=f"{ROOT}/work", help="uploads, warps and takes land here")
+p.add_argument("--samples", default=f"{ROOT}/examples/media", help="mp4s offered on the first screen")
+p.add_argument("--host", default="0.0.0.0")
+p.add_argument("--port", type=int, default=8412)
+p.add_argument("--max-clips", type=int, default=8)
+p.add_argument("--max-prep", type=int, default=8)
+args = p.parse_args()
+
+ASSETS = f"{ROOT}/assets"
+LIVE_SPEED = 0.33
+dev = torch.device("cuda")
+torch.set_grad_enabled(False) # main thread only -- grad mode is thread-local, and uvicorn runs sync
+# endpoints in a threadpool while /render runs in its own thread, so every GPU entry point below
+# carries its own @torch.no_grad(). Without it the VAE encode retains activations: 78 -> 177 GiB.
+os.makedirs(args.work, exist_ok=True)
+
+CLIPS, PREP, JOBS = {}, {}, {}
+GPU = threading.Lock() # one card: a render and a warp cannot overlap
+app = FastAPI()
+
+print("loading VGGT ...", flush=True)
+geometry = vggt(args.vggt, args.vggt_repo, dev)
+print("loading VAE ...", flush=True)
+vae = AutoencoderKLMiniMaxH3.from_pretrained(args.model_dir, subfolder="vae").to(dev).eval()
+print(f"loading {args.ckpt} + {os.path.basename(args.lora)} ...", flush=True)
+transformer = MiniMaxH3Transformer3DModel.from_pretrained(args.ckpt, torch_dtype=torch.bfloat16)
+transformer.load_lora_adapter(args.lora, weight_name="pytorch_lora_weights.safetensors", prefix=None)
+assert any("lora_" in n for n, _ in transformer.named_parameters()), "no LoRA weights landed"
+transformer.set_attention_backend("_native_cudnn")
+transformer.to(dev).eval()
+print(f"ready, {torch.cuda.memory_allocated() / 2**30:.1f} GiB resident", flush=True)
+
+
+# --- clip ingest ------------------------------------------------------------------------------------
+def normalise(src, dst):
+ """H.264 / CFR 24 / yuv420p / long edge <= 1280, rotation baked in. `:129` sends frames to the GPU at
+ their original resolution, so an un-normalised 4K upload is 1.8 GB on-card for 73 frames."""
+ subprocess.run(["ffmpeg", "-v", "error", "-y", "-autorotate", "1", "-i", src, "-vf",
+ "scale=1280:1280:force_original_aspect_ratio=decrease:force_divisible_by=2",
+ "-r", "24", "-c:v", "libx264", "-crf", "18", "-pix_fmt", "yuv420p",
+ "-c:a", "aac", dst], check=True)
+
+
+def cuts_of(fr):
+ """Hard-cut frames. VGGT reconstructs the span jointly, so a cut inside it poisons every camera
+ downstream -- this is a gate, not a warning. Cheap: 64x64 greyscale frame difference."""
+ x = torch.from_numpy(fr[:, ::max(1, fr.shape[1] // 64), ::max(1, fr.shape[2] // 64)]).float().mean(-1)
+ d = (x[1:] - x[:-1]).abs().mean(dim=(1, 2))
+ return [int(i) + 1 for i in torch.nonzero(d > torch.maximum(3 * d.median(), torch.tensor(14.0)))[:, 0]]
+
+
+def ingest(raw, name):
+ sha = hashlib.sha256(raw).hexdigest()[:16]
+ d = f"{args.work}/clips/{sha}"
+ os.makedirs(d, exist_ok=True)
+ mp4 = f"{d}/clip.mp4"
+ if sha not in CLIPS:
+ if not os.path.exists(mp4):
+ open(f"{d}/raw", "wb").write(raw)
+ normalise(f"{d}/raw", mp4)
+ os.remove(f"{d}/raw")
+ c = av.open(mp4)
+ fr = np.stack([f.to_ndarray(format="rgb24") for f in c.decode(video=0)])
+ c.close()
+ CLIPS[sha] = dict(path=mp4, fr=fr, n=len(fr), h=fr.shape[1], w=fr.shape[2], name=name, cuts=cuts_of(fr))
+ for k in list(CLIPS)[: max(0, len(CLIPS) - args.max_clips)]:
+ CLIPS.pop(k)
+ c = CLIPS[sha]
+ return dict(clip=sha, frames=c["n"], w=c["w"], h=c["h"], name=name, cuts=c["cuts"],
+ seconds=round(c["n"] / FPS, 2), lengths=[73, 124, 175, 243] if c["n"] >= 73 else []) # the take's length is free of the source's: a path can hold or slow the clip
+
+
+# --- geometry ---------------------------------------------------------------------------------------
+@torch.no_grad()
+def prepare(clip, start, span_end):
+ """Letterbox + one VGGT pass over source frames `start..span_end`, cached.
+
+ The key is the DECODED span, not `(clip, start, frames)`: `tmap[-1] = start + frames - n`, so the
+ freeze length changes which frames VGGT sees, and VGGT is a joint pass -- 50 frames and 73 frames do
+ not give the same tensors for the frames they share. Moving the freeze *frame* at a fixed `n` keeps
+ the span, so it is free; changing `n` costs one 2.0 s pass."""
+ key = (clip, start, span_end)
+ if key in PREP:
+ return PREP[key]
+ c = CLIPS[clip]
+ assert 0 <= start < span_end < c["n"], f"the window runs to source frame {span_end} but the clip has only {c['n']} frames"
+ t0 = time.time()
+ frames = torch.from_numpy(c["fr"][start : span_end + 1]).to(dev)
+ h, w = frames.shape[1:3]
+ s = FULL / max(h, w)
+ ch, cw = round(h * s), round(w * s)
+ ox, oy = (FULL - cw) // 2, (FULL - ch) // 2
+ full = torch.zeros(len(frames), FULL, FULL, 3, dtype=torch.uint8, device=dev)
+ full[:, oy : oy + ch, ox : ox + cw] = resize_u8(frames, (ch, cw))
+ del frames
+ canvas, cond_canvas = bucket(w, h)
+ a = canvas[0] / canvas[1]
+ bw, bh = (cw, round(cw / a)) if cw / ch <= a else (round(ch * a), ch)
+ box = (ox + (cw - bw) // 2, oy + (ch - bh) // 2, bw, bh, canvas[0] / bw)
+ S0 = reconstruct(geometry, to_input(full))
+ picture = torch.zeros(RES, RES, dtype=torch.bool, device=dev)
+ picture[round(oy * RES / FULL) : round((oy + ch) * RES / FULL), round(ox * RES / FULL) : round((ox + cw) * RES / FULL)] = True
+ P = dict(S0=S0, full0=full, box=box, canvas=canvas, cond_canvas=cond_canvas, start=start, picture=picture,
+ scale=s, ox=ox, oy=oy, ch=ch, cw=cw, ms=int(1000 * (time.time() - t0)))
+ PREP[key] = P
+ for k in list(PREP)[: max(0, len(PREP) - args.max_prep)]:
+ PREP.pop(k)
+ return P
+
+
+def plan(q):
+ """The payload -> (tmap, ramp, pf). One enum, not flags: `--ease` on a flat ramp is a static camera."""
+ start, n_out, shape = int(q["start"]), int(q["frames"]), q["shape"]
+ if shape.startswith("freeze"):
+ fz, n = int(q["freeze_frame"]), int(q["freeze_n"])
+ tail = n_out - n - (fz - start)
+ assert fz >= start and tail >= 0, f"freeze {fz}x{n} does not fit a {n_out}-frame window from {start}"
+ tmap = list(range(start, fz)) + [fz] * n + list(range(fz + 1, fz + 1 + tail))
+ ramp = torch.cat([torch.zeros(fz - start), torch.linspace(0, 1, n), torch.ones(tail)])
+ if shape == "freeze_sweep":
+ wt = torch.tensor([LIVE_SPEED] * (fz - start) + [1.0] * n + [LIVE_SPEED] * tail)
+ ramp = torch.cumsum(wt, 0) - wt[0]
+ ramp = ramp / ramp[-1]
+ pf = tmap.index(fz)
+ else:
+ tmap = list(range(start, start + n_out))
+ ramp = torch.ones(n_out) if shape == "hold" else torch.linspace(0, 1, n_out)
+ if shape == "sweep_ease":
+ ramp = (1 - torch.cos(math.pi * ramp)) / 2
+ if shape == "bounce":
+ ramp = (1 - torch.cos(2 * math.pi * ramp)) / 2
+ if shape == "swing":
+ ramp = torch.sin(2 * math.pi * ramp)
+ pf = 0
+ return tmap, ramp, pf
+
+
+def pivot_frac(P, u, v):
+ """A click at (u,v) in source-frame fractions -> `--pivot fx,fy`, which is a fraction of the CROP BOX
+ inside the 1280 letterbox, not of the source frame. Doing this conversion in the browser is what killed
+ 110 render-farm jobs, so it lives here. The clamp is the silent-NaN edge: an out-of-range window gives
+ an empty median, i.e. `zm = nan`, and 25 s of grey mud with no error."""
+ x0, y0, bw, bh, _ = P["box"]
+ fx = (P["ox"] + u * P["cw"] - x0) / bw
+ fy = (P["oy"] + v * P["ch"] - y0) / bh
+ return min(max(fx, 0.06), 0.94), min(max(fy, 0.06), 0.94)
+
+
+def unit(P, q):
+ """The path's frame and unit. `zm` = median depth in a 10% window around the pivot (default: the centre of
+ the picture) at `pivot_frame` (default: `start`), falling back to the whole picture when the window has no
+ depth (sky); `piv` = that point in the pivot frame's camera; `W` = the camera of frame `start`, the frame
+ every key is expressed in. Returns zi, zm, piv, W, piv_world, (fx, fy)."""
+ Z, start = P["S0"], P["start"]
+ zi = int(q.get("pivot_frame", start)) - start
+ assert 0 <= zi < len(P["full0"]), f"pivot frame {zi + start} outside the prepared span"
+ x0, y0, bw, bh, _ = P["box"]
+ fx, fy = pivot_frac(P, *[float(v) for v in q.get("pivot", [0.5, 0.5])])
+ r = RES / FULL
+ px, py, rw, rh = (x0 + fx * bw) * r, (y0 + fy * bh) * r, 0.05 * bw * r, 0.05 * bh * r
+ win = (slice(round(py - rh), round(py + rh)), slice(round(px - rw), round(px + rw)))
+ sub = Z["depth"][zi][win][Z["keep"][zi][win]]
+ if sub.numel() < 20:
+ sub = Z["depth"][zi][Z["keep"][zi] & P["picture"]]
+ zm = float(sub.median()) if sub.numel() else float("nan")
+ assert math.isfinite(zm), "no usable depth in this frame"
+ K = Z["intr"][zi]
+ piv = torch.tensor([(px - float(K[0, 2])) / float(K[0, 0]) * zm,
+ (py - float(K[1, 2])) / float(K[1, 1]) * zm, zm], device=dev)
+ W = Z["c2w"][0]
+ piv_world = Z["c2w"][zi][:3, :3] @ piv + Z["c2w"][zi][:3, 3]
+ return zi, zm, piv, W, piv_world, (fx, fy)
+
+
+def poses(P, q):
+ """Every prepared source frame's camera as a key (pos, look, roll) in the path's frame, plus the pivot."""
+ _, zm, _, W, piv_world, _ = unit(P, q)
+ Wi = torch.linalg.inv(W)
+ piv_P = (Wi[:3, :3] @ piv_world + Wi[:3, 3]).cpu().numpy()
+ out = describe((Wi[None] @ P["S0"]["c2w"]).cpu().numpy(), piv_P, zm)
+ x0, y0, bw, bh, _ = P["box"]
+ r = FULL / RES # each frame's lens as canvas fractions (fx/w, fy/h, cx/w, cy/h), exactly what /warp1 renders with, so the editor can look through a key
+ for p, K in zip(out, P["S0"]["intr"].cpu().numpy()):
+ p["k"] = [round(float(v), 5) for v in (K[0, 0] * r / bw, K[1, 1] * r / bh, (K[0, 2] * r - x0) / bw, (K[1, 2] * r - y0) / bh)]
+ return dict(src_poses=out, piv=(piv_P / zm).round(4).tolist(), zm=zm)
+
+
+@torch.no_grad()
+def geo(q):
+ """Everything up to and including the warp. Returns the folded session, the cameras and the gauges."""
+ start = int(q["start"])
+ P = PREP[(q["clip"], start, int(q["span_end"]))]
+ Z = P["S0"]
+ if q.get("path"): # keyframe path (recam/path.py): the pivot only sets the unit `zm` and the gauges
+ n_out, pf_src = int(q["frames"]), int(q.get("pivot_frame", q.get("freeze_frame", q["path"][0]["src"])))
+ else: # the parametric family: yaw / dolly / truck / boom about the pivot, one ramp
+ tmap, ramp, pf = plan(q)
+ n_out, pf_src = len(tmap), tmap[pf]
+ zi, zm, piv, W, piv_world, (fx, fy) = unit(P, {**q, "pivot_frame": pf_src}) # piv: --pivot-lock, always
+ if q.get("path"):
+ c2w_P, tmap, focal, speed = plan_path(q["path"], n_out, zm)
+ pf = tmap.index(pf_src) if pf_src in tmap else 0
+ idx = torch.tensor(tmap) - start
+ assert 0 <= int(idx.min()) and int(idx.max()) < len(P["full0"]), f"tmap {tmap[0]}..{tmap[-1]} outside the prepared span"
+ idx = idx.to(dev) # an out-of-range gather is a device-side assert, which kills the CUDA context for good
+ S = {k: v[idx] for k, v in Z.items()}
+ full = P["full0"][idx]
+ c2w, intr_t = S["c2w"].clone(), S["intr"].clone()
+ if q.get("path"):
+ c2w = W[None] @ torch.tensor(c2w_P, dtype=c2w.dtype, device=dev)
+ f = torch.tensor(focal, dtype=intr_t.dtype, device=dev)
+ intr_t[:, 0, 0] *= f
+ intr_t[:, 1, 1] *= f
+ yaw, dolly, truck, boom, aim = (float(q.get("yaw", 0)), float(q.get("dolly", 1)), float(q.get("truck", 0)),
+ float(q.get("boom", 0)), bool(q.get("aim", False)))
+ for ti in ([] if q.get("path") else range(n_out)):
+ th = math.radians(yaw * float(ramp[ti]))
+ rr = 1 + (dolly - 1) * float(ramp[ti])
+ R = torch.tensor([[math.cos(th), 0, math.sin(th)], [0, 1, 0], [-math.sin(th), 0, math.cos(th)]], device=dev)
+ delta = torch.eye(4, device=dev)
+ delta[:3, :3] = R
+ delta[:3, 3] = piv - R @ (rr * piv) - R @ torch.tensor(
+ [-truck * zm * float(ramp[ti]), boom * zm * float(ramp[ti]), 0.0], device=dev)
+ if aim:
+ a = piv / piv.norm()
+ b = piv - delta[:3, 3]
+ b = b / b.norm()
+ v, c = torch.cross(a, b, dim=0), float(a @ b)
+ sn = float(v.norm())
+ Kx = torch.zeros(3, 3, device=dev)
+ Kx[0, 1], Kx[0, 2], Kx[1, 0], Kx[1, 2], Kx[2, 0], Kx[2, 1] = -v[2], v[1], v[2], -v[0], -v[1], v[0]
+ delta[:3, :3] = torch.eye(3, device=dev) + Kx + Kx @ Kx * ((1 - c) / sn ** 2) if sn > 1e-8 else torch.eye(3, device=dev)
+ c2w[ti] = S["c2w"][ti] @ delta
+ intr_t[ti, 0, 0] *= rr
+ intr_t[ti, 1, 1] *= rr
+ w2c = torch.linalg.inv(c2w)
+ render, cov = warp(S, w2c, intr_t, full, P["box"], P["canvas"])
+ yy, xx = torch.meshgrid(torch.arange(RES, device=dev), torch.arange(RES, device=dev), indexing="ij")
+ g1 = torch.stack([xx, yy, torch.ones_like(xx)], -1).float().reshape(-1, 3)
+ near, behind, coll, ahead = [], [], [], []
+ for ti in range(n_out):
+ X = ((g1 @ torch.linalg.inv(S["intr"][ti]).T).reshape(RES, RES, 3) * S["depth"][ti][..., None]) \
+ @ S["c2w"][ti][:3, :3].T + S["c2w"][ti][:3, 3]
+ zd = (X - c2w[ti][:3, 3]) @ c2w[ti][:3, 2]
+ near.append(float((zd[S["keep"][ti]] < 0.1 * zm).float().mean()))
+ behind.append(float((zd[S["keep"][ti]] < 0).float().mean()))
+ coll.append(float(((X - c2w[ti][:3, 3]).norm(dim=-1)[S["keep"][ti]] < 0.05 * zm).float().mean()))
+ cb = S["keep"][ti].clone()
+ cb[: RES // 4] = cb[-(RES // 4):] = False
+ cb[:, : RES // 4] = cb[:, -(RES // 4):] = False
+ ahead.append(float(torch.quantile(zd[cb], 0.05)) / zm if cb.any() else 9.0)
+ g = dict(zm=zm, ahead=min(ahead), near=max(near), behind=max(behind), coll=max(coll),
+ coverage=float(cov.float().mean()),
+ moved=float((c2w[:, :3, 3] - S["c2w"][:, :3, 3]).norm(dim=-1).max()) / zm, # largest departure from the source camera anywhere in the take (a freeze-orbit returns to it at the end)
+ pivot_frac=[fx, fy], frames=n_out, tmap=tmap)
+ # the path view of whatever was authored: per-frame (pos, look) in W / zm, so the studio can turn a
+ # parametric move (the templates) into keys
+ Wi = torch.linalg.inv(W)
+ piv_P = (Wi[:3, :3] @ piv_world + Wi[:3, 3]).cpu().numpy()
+ g["cams"] = describe((Wi[None] @ c2w).cpu().numpy(), piv_P, zm)
+ g["piv"] = (piv_P / zm).round(4).tolist()
+ if q.get("path"):
+ g["speed"] = [round(x, 3) for x in speed]
+ return P, S, full, tmap, pf, c2w, intr_t, render, cov, g
+
+
+# --- endpoints --------------------------------------------------------------------------------------
+@app.get("/")
+def index():
+ return HTMLResponse(open(f"{HERE}/index.html").read()) # re-read per request, so frontend edits need no restart
+
+
+@app.get("/samples")
+def samples():
+ if not os.path.isdir(args.samples):
+ return []
+ return sorted(f for f in os.listdir(args.samples) if f.endswith(".mp4"))
+
+
+@app.post("/upload")
+async def upload(file: UploadFile = File(...)):
+ return ingest(await file.read(), file.filename)
+
+
+@app.post("/sample")
+async def sample(req: Request):
+ q = await req.json()
+ path = os.path.join(args.samples, os.path.basename(q["name"]))
+ return ingest(open(path, "rb").read(), os.path.basename(path))
+
+
+@app.get("/frame/{clip}/{i}.jpg")
+def frame(clip: str, i: int):
+ if clip not in CLIPS:
+ raise HTTPException(404, "unknown clip")
+ c = CLIPS[clip]
+ d = f"{args.work}/clips/{clip}/f"
+ os.makedirs(d, exist_ok=True)
+ fp = f"{d}/{i}.jpg"
+ if not os.path.exists(fp):
+ Image.fromarray(c["fr"][min(max(i, 0), c["n"] - 1)]).save(fp, "JPEG", quality=88)
+ return FileResponse(fp)
+
+
+@app.post("/prepare")
+async def prepare_ep(req: Request):
+ q = await req.json()
+ with GPU:
+ P = prepare(q["clip"], int(q["start"]), int(q["span_end"]))
+ r = poses(P, q)
+ return dict(box=list(P["box"]), canvas=list(P["canvas"]), cond_canvas=list(P["cond_canvas"]), ms=P["ms"], **r)
+
+
+@app.post("/cloud")
+async def cloud_ep(req: Request):
+ """The 3D editor's scene: one source frame's coloured point cloud in the path's frame (W / zm, see
+ recam/path.py), one point every `stride` pixels, nothing beyond 10 pivot depths."""
+ q = await req.json()
+ start, stride = int(q["start"]), int(q.get("stride", 5))
+ with GPU:
+ P = prepare(q["clip"], start, int(q["span_end"]))
+ Z, i = P["S0"], int(q["frame"]) - start
+ assert 0 <= i < len(P["full0"]), f"frame {q['frame']} outside the prepared span"
+ _, zm, _, W, _, _ = unit(P, q)
+ Wi = torch.linalg.inv(W)
+ yy, xx = torch.meshgrid(torch.arange(RES, device=dev), torch.arange(RES, device=dev), indexing="ij")
+ g1 = torch.stack([xx, yy, torch.ones_like(xx)], -1).float().reshape(-1, 3)
+ rgb = resize_u8(P["full0"][i : i + 1], (RES, RES))[0]
+ X = ((g1 @ torch.linalg.inv(Z["intr"][i]).T).reshape(RES, RES, 3) * Z["depth"][i][..., None]) \
+ @ Z["c2w"][i][:3, :3].T + Z["c2w"][i][:3, 3]
+ X = (X @ Wi[:3, :3].T + Wi[:3, 3]) / zm
+ m = (Z["keep"][i] & P["picture"] & (Z["depth"][i] < 10 * zm))[::stride, ::stride]
+ pts, cols = X[::stride, ::stride][m].cpu(), rgb[::stride, ::stride][m].cpu()
+ return dict(n=len(pts), zm=zm, pts=pts.reshape(-1).numpy().round(3).tolist(), rgb=cols.reshape(-1).tolist())
+
+
+@app.post("/warp1")
+async def warp1_ep(req: Request):
+ """One key's still: source frame `src` warped to the camera (`pos`, `look`, in the path's frame and unit),
+ at `cond_canvas`, as JPEG. What the model would be given at that instant."""
+ q = await req.json()
+ with GPU:
+ P = prepare(q["clip"], int(q["start"]), int(q["span_end"]))
+ Z, i = P["S0"], int(q["src"]) - int(q["start"])
+ assert 0 <= i < len(P["full0"]), f"source frame {q['src']} outside the prepared span"
+ _, zm, _, W, _, _ = unit(P, q)
+ pos, look = np.asarray(q["pos"], float) * zm, np.asarray(q["look"], float) * zm
+ c2w_P = np.eye(4)
+ c2w_P[:3, :3], c2w_P[:3, 3] = look_at(pos, look), pos
+ c2w = (W @ torch.tensor(c2w_P, dtype=W.dtype, device=dev))[None]
+ S = {k: v[i : i + 1] for k, v in Z.items()}
+ intr = S["intr"].clone()
+ intr[:, 0, 0] *= float(q.get("focal", 1))
+ intr[:, 1, 1] *= float(q.get("focal", 1))
+ render, _ = warp(S, torch.linalg.inv(c2w), intr, P["full0"][i : i + 1], P["box"], P["canvas"])
+ img = resize_u8(render, P["cond_canvas"][::-1])[0].cpu().numpy()
+ buf = io.BytesIO()
+ Image.fromarray(img).save(buf, "JPEG", quality=82)
+ return Response(buf.getvalue(), media_type="image/jpeg")
+
+
+@app.post("/warp")
+async def warp_ep(req: Request):
+ """Tier 1. The whole trajectory, 0.24 s. The pane that decides whether a take is worth 25 s of B200."""
+ q = await req.json()
+ t0 = time.time()
+ with GPU:
+ P, S, full, tmap, pf, c2w, intr_t, render, cov, g = geo(q)
+ cc = P["cond_canvas"]
+ truth = resize_u8(render, cc[::-1]).cpu() # what the model is actually given
+ holes = None if q.get("lite") else truth.clone()
+ m = None if q.get("lite") else ~resize_u8(cov[..., None].to(torch.uint8) * 255, cc[::-1])[..., 0].bool().cpu()
+ if holes is not None:
+ holes[m] = torch.tensor([255, 0, 200], dtype=torch.uint8)
+ sketch = None if q.get("lite") else render.cpu()
+ d = f"{args.work}/warp/{q['clip']}"
+ os.makedirs(d, exist_ok=True)
+ tag = str(int(time.time() * 1000))
+ write_mp4(truth, fps=int(FPS), output_path=f"{d}/truth_{tag}.mp4")
+ g.update(truth=f"/warpfile/{q['clip']}/truth_{tag}.mp4",
+ cond_canvas=list(cc), canvas=list(P["canvas"]))
+ if sketch is not None:
+ write_mp4(holes, fps=int(FPS), output_path=f"{d}/holes_{tag}.mp4")
+ write_mp4(sketch, fps=int(FPS), output_path=f"{d}/sketch_{tag}.mp4")
+ g.update(holes=f"/warpfile/{q['clip']}/holes_{tag}.mp4", sketch=f"/warpfile/{q['clip']}/sketch_{tag}.mp4")
+ g["ms"] = int(1000 * (time.time() - t0))
+ print(f"[warp] {torch.cuda.memory_allocated() / 2**30:.1f} GiB live, {torch.cuda.max_memory_allocated() / 2**30:.1f} peak", flush=True)
+ return g
+
+
+@app.get("/warpfile/{clip}/{name}")
+def warpfile(clip: str, name: str):
+ if clip not in CLIPS:
+ raise HTTPException(404, "unknown clip")
+ return FileResponse(f"{args.work}/warp/{clip}/{os.path.basename(name)}")
+
+
+@torch.no_grad()
+def do_render(job, q):
+ """`inference/sample.py`'s render path, resident. The seed lives one line before the encodes on purpose:
+ `pack` consumes global CPU RNG and the VAE posterior consumes global CUDA RNG, and the noise-augmented
+ condition rows are fed to the model and never overwritten -- so `torch.manual_seed` is what makes a take
+ reproducible."""
+ d = f"{args.work}/takes/{job}"
+ os.makedirs(d, exist_ok=True)
+
+ def stage(name, pct):
+ JOBS[job].update(stage=name, pct=pct, t=round(time.time() - JOBS[job]["t0"], 1))
+ print(f"[{job}] {name} {torch.cuda.memory_allocated() / 2**30:.1f} GiB live, "
+ f"{torch.cuda.max_memory_allocated() / 2**30:.1f} peak", flush=True)
+ json.dump(JOBS[job], open(f"{d}/status.tmp", "w"))
+ os.replace(f"{d}/status.tmp", f"{d}/status.json")
+
+ try:
+ with GPU:
+ stage("warp", 5)
+ P, S, full, tmap, pf, c2w, intr_t, render, cov, g = geo(q)
+ canvas, cc, box = P["canvas"], P["cond_canvas"], P["box"]
+ x0, y0, bw, bh, _ = box
+ n_out = len(tmap)
+ stage("encode", 15)
+ torch.manual_seed(int(q.get("seed", 1234))) # the one-line seed fix
+ render_c = resize_u8(render, cc[::-1])
+ source = resize_u8(full[:, y0 : y0 + bh, x0 : x0 + bw], canvas[::-1])
+ cond = resize_u8(full[:, y0 : y0 + bh, x0 : x0 + bw], cc[::-1])
+ dd = {"cond": encode_video(vae, cond)[0], "render": encode_video(vae, render_c)[0],
+ "target": encode_video(vae, source)[1]}
+ embed = torch.load(f"{ASSETS}/fixed_embed_{n_out}.pt", weights_only=False)
+ audio_x0 = torch.load(f"{ASSETS}/silence_audio_{n_out}.pt", weights_only=True)["audio_x0"].float()
+ batch = pack(dd["cond"], dd["render"], dd["target"], embed["prompt_embeds"][0], embed["text_token_tags"], audio_x0)
+ rows = denoise(transformer, batch, args.steps, args.flow_shift, dev,
+ on_step=lambda i, n: stage(f"forward {i + 1}/{n}", 25 + int(45 * i / n)))
+ stage("decode", 75)
+ out = decode_video(vae, rows, dd["target"].shape[1:])
+ src_c, ren_c = source.cpu(), render_c.cpu()
+
+ stage("write", 90)
+ for name, fr in ("out", out), ("render", ren_c), ("source", src_c):
+ write_mp4(fr, fps=int(FPS), output_path=f"{d}/{name}.mp4")
+ write_mp4(torch.cat([src_c, resize_u8(ren_c, canvas[::-1]), out], 2), fps=int(FPS), output_path=f"{d}/grid.mp4")
+ Image.fromarray(out[-1].numpy()).save(f"{d}/last.png")
+ JOBS[job].update(gauges=g, done=True)
+ stage("done", 100)
+ except Exception as e:
+ JOBS[job].update(error=f"{type(e).__name__}: {e}", done=True)
+ stage("error", 100)
+ if isinstance(e, torch.AcceleratorError):
+ die(e)
+ raise
+
+
+def die(e):
+ """A sticky CUDA error (device-side assert, illegal address) cannot be cleared in-process: every later
+ kernel fails too and the page goes dead. Exit 3; run.sh relaunches on that code only (~2 min reload)."""
+ print(f"CUDA context poisoned, exiting for restart: {e}", flush=True)
+ threading.Timer(0.5, os._exit, [3]).start()
+
+
+@app.exception_handler(torch.AcceleratorError)
+async def cuda_dead(req, e):
+ die(e)
+ return JSONResponse({"error": f"GPU fault: {e}"[:300] + " -- service restarting, ~2 min"}, status_code=503)
+
+
+NJOB = itertools.count()
+
+
+@app.post("/render")
+async def render_ep(req: Request):
+ q = await req.json()
+ job = f"{int(time.time())}_{q['clip'][:6]}_{next(NJOB)}" # two clicks in the same second must not share a job dir
+ JOBS[job] = dict(job=job, t0=time.time(), stage="queued", pct=0, done=False, payload=q)
+ threading.Thread(target=do_render, args=(job, q), daemon=True).start()
+ return dict(job=job)
+
+
+@app.get("/job/{job}")
+def job_ep(job: str):
+ if job not in JOBS:
+ raise HTTPException(404, "unknown job")
+ j = dict(JOBS[job])
+ j.pop("t0", None)
+ return j
+
+
+@app.get("/take/{job}/{name}")
+def take(job: str, name: str):
+ if job not in JOBS:
+ raise HTTPException(404, "unknown job")
+ return FileResponse(f"{args.work}/takes/{job}/{os.path.basename(name)}")
+
+
+uvicorn.run(app, host=args.host, port=args.port, log_level="warning")
diff --git a/service/index.html b/service/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..a3404a52cbf66f716155f6203ae06994c27614ea
--- /dev/null
+++ b/service/index.html
@@ -0,0 +1,753 @@
+recam — camera moves for footage you already have
+
+
+
+
+
+ Give it a camera it never had
+ Upload a clip. Its geometry is reconstructed at once; you then place a few camera keys in 3D
+ — where the camera is, what it looks at, which moment of the clip it shows — and the model renders
+ the view that was never shot.
+
+
Drop a video here, or click to choosemp4 / mov / webm · a few seconds is plenty
+
+
or start from a sample plate
+
+
+
+
+
+ The studio
+ The left pane is exactly what the model will be conditioned on, at the resolution it will be
+ conditioned at. Each key is one camera: a position, a point it looks at, the source frame it shows and the
+ output frame it lands on. Between keys the camera glides; the same source frame at two keys is a freeze.
+
+ start from a move:
+ orbit
+ push in
+ slide
+ crane
+ freeze + orbit
+ the clip's own camera
+ each replaces the keys below · Ctrl+Z undoes
+
+
+
+
+ what the model sees
+ where the pixels are missing
+
+
+
+
preview frame 0 ▶
+
+
+
+
+
+
the window
+
+
the strip is the whole clip: shaded = the frames reconstructed, white ticks = your keys, red = a hard cut
+
+ window starts at frame · moving it reconstructs again and resets the keys
+
+
+
take length
+
+
back to the overview
+
+
+
+
+
+
+ fine-tune the keys:
+ + key at the preview frame
+ clear the keys
+
+
+
+
+
+
+ Render this take
+ ← another clip
+
+
+
+
+
+
+ Rendering
+ Three forwards of the 4-step student at the 480 class. The warp is already done; what happens now is
+ the model filling in every pixel the original camera never saw.
+
+
+
+
+ The take
+
+
the original frame, cropped
+
+
+
+
+ play / pause
+
+
+
+
+
+
+
+
diff --git a/service/run.sh b/service/run.sh
new file mode 100644
index 0000000000000000000000000000000000000000..be7ace01bda443f34d98a08972cfd9c51c40ea89
--- /dev/null
+++ b/service/run.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# The demo service. One card holds VGGT-Omega + VAE + the finetuned transformer + the DMD LoRA (~77 GiB).
+# CARD=0 service/run.sh --port 8412
+export CUDA_VISIBLE_DEVICES=${CARD:-0}
+export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
+export PYTORCH_ALLOC_CONF=expandable_segments:True
+cd "$(dirname "$0")/.."
+# Exit code 3 = the service found its CUDA context poisoned and asked to be reloaded; anything else stops.
+while :; do
+ python service/app.py "$@"
+ [ $? = 3 ] || break
+ sleep 2
+done
diff --git a/videos-all/candidates.md b/videos-all/candidates.md
new file mode 100644
index 0000000000000000000000000000000000000000..bfa308013d141ecd1ff28d1b4a7e8c2918dc5f76
--- /dev/null
+++ b/videos-all/candidates.md
@@ -0,0 +1,246 @@
+# Meridian (recam) release — candidate table
+
+**Every row is a job recipe, not an mp4.** All candidates get re-rendered, so the plate path + 4th
+field (args) is what matters. `out.mp4 exists?` only tells you whether a reference render is on disk.
+
+- **ckpt column**: `r3-200` = `/mnt/juicefs-cache/yun/recam_runs/recam3/full-000200` (the release ckpt).
+ Rows marked `r2` have **no 5th field** in the job line = old recam2 → must be re-queued with the ckpt.
+- **Farm**: gpu5 `/mnt/juicefs-cache/yun/recam_infer/`; job line = `name|plate|pivot|args|ckpt`.
+ Plate paths in this table were verified present on gpu5 (39/39) in one batched `ssh`; `out.mp4`
+ existence read from `out//out.mp4` (all 56 checked = present).
+- **Doc handles**: `R` = `wm/README.md` · `SV` = `memory/recam-shot-vocabulary.md` ·
+ `SC` = `memory/recam-subject-classes.md` · `WD` = `memory/wm-demo-batch.md` ·
+ `NVT` = `memory/recam-novel-view-training.md` · `SBT` = `recam/SPORTS_BT_PATHS.md` ·
+ `AT2` = `recam/AT2_COMPARISON.md` · `ATL` = `memory/atlas-reproduction.md` · `IV` = `recam/infer_video.py`.
+- **Pivot** is the 3rd field and is *not* in the args column; it is quoted in the `why` cell where it matters.
+
+## Three traps that decide several rows
+
+1. **Ramp semantics** (`IV:103-113`, read them before writing any new job): `--sweep`, `--bounce`,
+ `--swing` each imply a linear 0→1 base ramp. **No ramp flag (or `--ease` alone) = `ramp ≡ 1` = a
+ constant full offset = fixed new viewpoint, camera never moves.** That is deliberate for the
+ `rv_w1_*` / `va_*` / `st3_*` rows below. Before 2026-09-07 `--bounce`/`--swing` without `--sweep`
+ silently rendered zero motion — "done 队列 3180 个 job 里有 966 个(30%)属于这一类" (`R:2192-2212`).
+ Any *old* mp4 with `--bounce` and no `--sweep`/`--freeze` may be an identity render; **re-rendering
+ today fixes it**, so those recipes are still valid, but do not trust their existing mp4.
+2. **`--live-speed` is not slow-motion.** `IV:57`: it is the *angular speed of the camera* in the live
+ lead-in/tail relative to the frozen frames. `tmap` is untouched — there is no source-slowdown flag.
+ A slowed-source demo needs the plate resampled first (`wm/srcspeed.py`), not a CLI flag.
+3. **Coverage/hole% are not quality gates.** "Coverage measures how much the model had to invent, not
+ how well it invented it" (`SC:448`); `dive_bullet` is a flawless 175-frame render with no diver
+ (`SC:258`); `rp_w_octopus_0_crane_up`/`rp_w_seaturtle_0_dive` score high with no subject in frame —
+ "Drop them" (`SC:426-428`). Every row below is justified by an eyeball verdict, not a number.
+
+---
+
+## A — camera control: same plate × 4 moves
+
+**No Commons plate has a complete recam3 4-move set.** A1/A2 below are the two plates with the best
+per-move evidence; the missing moves are new job lines.
+
+| slot | job name | plate (abs path on gpu5, origin) | frames | args (4th field) | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| A1 orbit | `wj_mixerblr_r28` | `src/w_mixerblr.mp4` — Commons (concrete-mixer truck, Bangalore street) | 73 | `--yaw -28 --bounce --sweep` | r3-200 | Y | "`R28S` … **8/10 strong.** The default." `SV:348`; mixerblr is the **only plate clean on all four** magnitudes `SV:372-378` | N |
+| A1 orbit-wide | `wq_mixerblr_y70` | same | 73 | `--yaw -70 --bounce --sweep` | r3-200 | Y | "yaw is cheap and safe, translation is not"; new default `--yaw -45 --bounce --sweep`, −70 is the probe `SV:381,385-386` | N |
+| A1 push | — | same | 73 | `--dolly 0.35 --zoom 1 --ease --sweep` | r3-200 | — | ladder cell `--dolly 0.35 --zoom 1 --ease` = "ok, ends as a macro" on mixerblr `SV:376` | **Y** (exact args at left) |
+| A1 truck-arc | — | same | 73 | `--truck 0.5 --ease --sweep` | r3-200 | — | ladder cell `--truck 0.5 --ease` = "ok" on mixerblr (it FAILs on forge and wellington) `SV:375` | **Y** |
+| A1 crane | — | same | 73 | `--boom 0.35 --ease --sweep --aim` | r3-200 | — | crane untested on this plate; `--boom 0.35 --ease --sweep` is the shipped crane recipe (`wh_pinnawala_crane`), `--aim` because a no-aim boom is "a vertical truck with a level optical axis" | **Y** |
+| A1 orbit+push (alt) | `wj_mixerblr_op` | same | 73 | `--yaw -22 --dolly 0.6 --zoom 1 --bounce --sweep` | r3-200 | Y | the `orbpush` idiom; keep as the 5th move if a 4-up grid needs a hero | N |
+| A2 orbit | `wh_pinnawala_r28` | `src/w_pinnawala.mp4` — Commons (elephants bathing, Pinnawala) | 73 | `--yaw -28 --bounce --sweep` | r3-200 | Y | "Confirmed keepers: … **elephants in grass** … textured mid-shot subject, visible ground plane, a background at a different depth" `SC:14` | N |
+| A2 push | `wj_pinnawala_push` | same | 73 | `--dolly 0.45 --zoom 1 --ease --sweep` | r3-200 | Y | "`PUSHS` … **3/3 strong.** Safest shot on live video." `SV:350` | N |
+| A2 crane | `wh_pinnawala_crane` | same | 73 | `--boom 0.35 --ease --sweep` | r3-200 | Y | same batch as the r28; pivot `0.5,0.55` (the r28 twin uses the same) | N |
+| A2 truck-arc | — | same | 73 | `--truck 0.35 --ease --sweep` | r3-200 | — | "`TRK` … **keeper, 2/3.** Best reveal shot" `SV:351`; 0.35 not 0.5 because truck 0.5 is the cell that fails on scenic plates `SV:375` | **Y** |
+
+*A2 alternate if a human subject is preferred over an animal*: `src/w_forge.mp4` (Commons blacksmith,
+"a forge" in the keeper list `SC:14`) — `wj_forge_r28` (`--yaw -28 --bounce --sweep`) and
+`wj_forge_deep` (`--dolly 0.70 --zoom 1 --ease --sweep`) both exist on r3-200. **Do not put a truck on
+forge**: `--truck 0.5 --ease` = "**FAIL** subject slides out, only coal left" `SV:375`.
+*Architecture option*: `v3_cityhall_r3_243` (`src/w_cityhall6.mp4`, `--dolly 0.45 --zoom 1 --ease --sweep
+--frames 243`, r3-200, out.mp4 Y) — "243 f … holds perfectly on cityhall" `NVT:156`; it needs 3 new
+jobs for the other moves. A cathedral nave is *not* a good 4-move plate: "on a corridor plate, **never
+spend GPU time on an orbit**" `SV:109`.
+
+---
+
+## B — time control on non-sport everyday footage
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| B1 plain passage | `wj_taikoclare_r28` | `src/w_taikoclare.mp4` — Commons (taiko drummers on a plaza) | 73 | `--yaw -28 --bounce --sweep` | r3-200 | Y | the live-camera control for the freeze; `R28S` = "8/10 strong. The default." `SV:348` | N |
+| B1 freeze hold | `wo_taikoclare_btp` | same | 73 | `--freeze 42:24 --yaw -28 --dolly 0.55 --zoom 1` | **r2 (no 5th field)** | Y | "taikoclare … freeze 42, yaw −28 + dolly 0.55 — **best of the batch**" `SV:398`; the −45 twin FAILs (near drum smears) `SV:399` | **Y — re-queue the identical args with `…|/mnt/juicefs-cache/yun/recam_runs/recam3/full-000200`** |
+| B1 slowed source | — | `src/w_taikoclare.mp4` resampled ×0.5 | 73 | `--yaw -28 --bounce --sweep` on the slowed plate | r3-200 | — | **there is no CLI slow-motion flag** — `--live-speed` only changes camera angular speed `IV:57`. Slow the plate first (`wm/srcspeed.py`), then re-use the B1-plain args | **Y (plate prep + job)** |
+| B2 one-shot (cat) | `catAR_B` | `/home/chenyun/cat2.mp4` — user's own footage | 175 | `--frames 175 --start 0 --freeze 123:52 --sweep --yaw -45 --bounce` | r3-200 | Y | "Bullet time on live video works — `--freeze` is in-distribution" `SV:388`; log: pivot depth 0.421, coverage 0.673. **Caveat: tail = 175−52−123 = 0, so it ends frozen — there is no resume.** | N |
+| B2 true live→freeze→orbit→resume | — | `/home/chenyun/cat2.mp4` | 175 | `--frames 175 --start 0 --freeze 60:60 --sweep --bounce --yaw -45 --live-speed 0.33 --pivot-lock` | r3-200 | — | tail = 175−60−60 = **55 live frames** = the resume the brief asks for. **No `--live-speed` job exists anywhere in the 4054-line corpus** — this idiom is entirely new work | **Y** |
+| B2 3-part control | `catAR_C1` / `C2` / `C3` | `/home/chenyun/cat2.mp4` | 73 ea. | `--frames 73 --start 0 --yaw -30 --sweep --bounce` / `--frames 73 --start 73 --freeze 73:73 --yaw -45 --bounce` / `--frames 73 --start 74 --freeze 123:24 --yaw -15 --ease` | r3-200 | Y | the shipped 3-chunk cut (`cat_film_3chunk.mp4`, 9.1 s) — use as the split-shot counter-example to the one-shot. **`catAR_B_r2` is a recam2 A/B control, not a take** | N |
+
+---
+
+## C — how-it-works 4-panel (source / warp / output / invented)
+
+**`wm/howitworks.mp4` has no build script and no shot table anywhere in the repo** (grep over `*.sh`/`*.py`
+returns nothing; only the index line `R:25` "四格拆解 … 三个机器人 take"). The three takes below are
+reconstructed from the `holes.py` table (`R:458-500`), which is the measurement that panel 4 displays.
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| C1 | `rv_w1_yawr` | `src/pi_w1.mp4` — Physical Intelligence π0.5 folding (robot-company reel) | 175 | `--yaw 24 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | hole **30.0%**, A/B 0.45, S 1.03 — the largest hole in the table, i.e. the most invented pixels to show `R:470` | N |
+| C2 | `rv_nx1_yaw` | `src/nx_w1.mp4` — 1X NEO bed-making (robot-company reel) | 175 | `--yaw 22 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | hole 27.3%, A/B 0.29 — second platform, same move `R:474` | N |
+| C3 | `rv_fhs2` | `src/fhs2.mp4` — Figure 02 Helix sorting (robot-company reel) | 175 | `--dolly 0.72 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | hole 20.6%, A/B 0.15, S 0.95 — the dolly/vertigo case, third platform `R:475` | N |
+| C alt | `hero_nx1_cr` | `src/nx_w1.mp4` | 175 | `--sweep --ease --boom 0.45 --dolly 1.30 --zoom 1 --aim --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "**干净(最佳)**:两台 NEO 与床全程一致…源片截掉的双腿被补全,脚落在地板上" `R:2762` — tells "invented" as a *success* story, not just a hole | N |
+
+> Note for panel 4: holes in `render.mp4` are **flat grey 128**, not black — detect with
+> `(|rgb−128| ≤ 2).all(-1)`; the A/B ratio "量的是『稳』,不是『对』" (`R:~500`).
+
+---
+
+## D1 — robots, multi-camera parallel (2 events)
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| D1 ev1 | `va_nx_r25` | `src/nx_w1.mp4` — 1X NEO (robot-company reel) | 124 | `--pivot-lock --start 0 --frames 124 --canvas 1920x1088 --full 1920 --yaw -25` | r3-200 | Y | timing corr **0.982** vs null −0.64; the six-cam set is "时序相关 0.96–0.98,lag 0 或 ±1…抓取/放开落在同一帧的 ±42 ms 内" `R:1827` | N |
+| D1 ev1 | `va_nx_lo` | same | 124 | `--pivot-lock --start 0 --frames 124 --canvas 1920x1088 --full 1920 --boom -0.22 --aim` | r3-200 | Y | timing corr **0.983**, the best of the six `R:1826` | N |
+| D1 ev2 | `va_pi3_hi` | `src/pi_w3.mp4` — π folding (robot-company reel) | 124 | `--pivot-lock --start 0 --frames 124 --canvas 1920x1088 --full 1920 --boom 0.30 --aim` | r3-200 | Y | "**干净**:俯视双臂叠衣,后方货架一致",timing 0.926 `R:2745` | N |
+| D1 ev2 | `va_pi3_l25` | same | 124 | `--pivot-lock --start 0 --frames 124 --canvas 1920x1088 --full 1920 --yaw 25` | r3-200 | Y | "**干净**:左侧机位,臂结构、后方货架一致" `R:2746` | N |
+
+**Do not propose** `va_pi3_wide` (`--dolly 1.50`, pure pull): "**拒动**:输出就是源机位" `R:2748`.
+For a 7-up rig sheet use `rig_pi1.json` (`rv_pi1_cm18…cp18`), but **cap a human-facing cut at ±11°** —
+`cp18`'s burned-in caption garbles to "eco astorgmoas, fo speed" plus an invented purple logo `R:2787`.
+
+---
+
+## D2 — robots, wrist-cam (`--dolly … --zoom 1 --pivot-lock`, pivot on the hand)
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| D2 | `rv_as3_wr` | `src/as_w3.mp4` — Astribot S1 (robot-company reel) | 175 | `--sweep --ease --dolly 0.45 --zoom 1 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "**最好**:80% 处夹爪抓圆柱的微距" — **trim to 150 frames**, the last 15% goes wrong `R:2613` | N (but cut `@150`) |
+| D2 | `rv_un3_wr` | `src/un_w3.mp4` — Unitree G1 kitchen (robot-company reel) | 175 | `--sweep --ease --dolly 0.55 --zoom 1 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "**意外出彩**:越过手臂钻进打开的洗碗机…模型编出连贯的洗碗机内部" `R:2616` — the interior is **invented, not reconstructed**; caption it honestly | N |
+| D2 | `rv_gm2_wr` | `src/gm2_w2.mp4` — Gemini Robotics / Apollo (robot-company reel) | 175 | `--sweep --ease --dolly 0.45 --zoom 1 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "好,灵巧手 + 蓝袋子,warp 洞只有 2%" `R:2615` | N |
+
+**Do not propose** `rv_tri_wr` ("穿过双臂后成了真人脸特写,**不用**" `R:2623`), `rv_al1_wr` (the one
+non-FOLLOWED take, "输出 ≈ 源机位" `R:2624`), `rv_pi6_wr` (末帧黑块 `R:2620`), `rv_op1_wr` (lands on a
+real person's torso, caption deforms `R:2622`), or the early `rv_w1_wrist55/45/35` ladder ("**构图错了**" `R:1159,1198`).
+
+---
+
+## D3 — world-model outputs re-cameraed (`wm_*`; plate is a restored still from the reel)
+
+All share `--freeze 0:124 --start 0 --frames 124 --canvas 1920x1088 --full 1920`, pivot `none`.
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| D3 | `wm_cs_truck_orbit_l` | `inbox/cs_truck_hi.png` — NVIDIA Cosmos world-model reel | 124 | `--yaw -24 --freeze 0:124 --start 0 --frames 124 --canvas 1920x1088 --full 1920` | r3-200 | Y | coverage 0.848, "**best of batch**" `WD:116`; "**Cosmos (cs_*) is the best source in the set — 8/8 usable**" `WD:73` | N |
+| D3 | `wm_oa_arm_orbit_l` | `inbox/oa_arm_hi.png` — Odyssey world-model reel | 124 | `--yaw -24 --freeze 0:124 --start 0 --frames 124 --canvas 1920x1088 --full 1920` | r3-200 | Y | "`oa_arm_orbit_l` **is the standout**" `WD:79` | N |
+| D3 | `wm_chef_arms_orbit` | `inbox/chef2169_hi.png` — NVIDIA GR00T chef re-cut | 124 | `--yaw 24 --freeze 0:124 --start 0 --frames 124 --canvas 1920x1088 --full 1920` | r3-200 | Y | "**Best: `wm_chef_arms_orbit`**" `WD:100`; coverage 0.908, no logo/title-card/watermark | N |
+
+**Do not propose**: `wm_gn_lab_orbit_r` (0.712, "**fail** — foreground arm badly smeared" `WD:118`);
+`wm_cs_diag_push` ("clean but ends nose-to-nose with a box pallet" `WD:113`); the `chef875` pair
+("clean but subject-less" `WD:102`); `g3_fld` with any push/orbit (prow at depth 0.04 — use
+`wm_g3_fld_crane --boom 0.26` `WD:22-24`); `ap_std` with a crane (legs-only crop `WD:25-26`).
+The reel sources are `--sweep`-hostile: "on a fast-cut news package, `--sweep` is the wrong tool" `SC:420`
+— that is why this whole batch uses `--freeze 0:124` on a hand-picked still.
+
+---
+
+## D4 — everyday / user footage
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| D4 | `v3_cityhall_r3_243` | `src/w_cityhall6.mp4` — Commons (city hall) | 243 | `--dolly 0.45 --zoom 1 --ease --sweep --frames 243` | r3-200 | Y | "243 f (10.1 s at 24 fps) holds perfectly on cityhall" `NVT:156`; coverage 0.830 | N |
+| D4 | `v3_mazatlan_r3_175` | `src/w_mazatlan.mp4` — Commons (Mazatlán street) | 175 | `--dolly 0.45 --zoom 1 --ease --sweep --frames 175` | r3-200 | Y | "175 f holds identity to the last frame on prescott / mazatlan / cityhall" `NVT:155`; coverage 0.905 | N |
+| D4 | `v3_prescott_r3_175` | `src/w_prescottengine.mp4` — Commons (traction engine) | 175 | `--yaw -45 --bounce --sweep --frames 175` | r3-200 | Y | same `NVT:155` line, and it is the yaw arm at the new `-45` default `SV:385` | N |
+
+The user's own cat clip (`catAR_C1`, row B2) is the strongest "user footage" take and doubles here.
+**Do not propose** `wm_walkway_pushs` (coverage 0.451) or `wellington_trk` ("f72 **replaced the scene
+with a hallucinated woman's portrait**" `SV:356`) or `helipad_r28s` (helicopter returns mirrored `SV:358`).
+
+---
+
+## D5 — sports bullet time
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| D5 | `y_boxing_bullet` | `inbox/sp_boxing_slowmo.mp4` — YouTube broadcast | 175 | `--pivot-lock --start 320 --freeze 360:95 --yaw -18 --dolly 0.35 --zoom 1 --bounce --frames 175` | r3-200 | Y | "**Surprise survivor: boxing.** … one of the cleanest takes of the whole session — anatomy, ring ropes and sponsor-board text all hold for 175 frames" `SC:228-230` | N |
+| D5 | `y_maroney_bullet` | `inbox/sp_maroney_vault_4k.mp4` — YouTube (Olympic gymnastics) | 175 | `--pivot-lock --start 300 --freeze 340:95 --yaw -20 --dolly 0.35 --zoom 1 --bounce --frames 175` | r3-200 | Y | "**Winners (all 175 frames clean):** `maroney_bullet` …" — "Olympic gymnastics is the single best-behaved sports class found so far" `SC:243-245` | N |
+| D5 | `y_bboy_orbit` | `inbox/sp_bboy_battle.mp4` — YouTube (breaking) | 175 | `--pivot-lock --start 1230 --yaw -15 --dolly 0.5 --zoom 1 --sweep --ease --frames 175` | r3-200 | Y | yaw −15 / dolly 0.5 obeys the action-amplitude law (yaw ≤ ~18°, dolly ≥ ~0.5) `SV:436`; "`y_bboy_orbit` and `y_duplantis_orbit` (yaw −15, dolly 0.5) are **the best takes of the wave**" `SV:451`; also in the Winners list `SC:244` | N |
+| D5 alt (Commons-only) | `sp_bouldering_hang_r3` | `src/sp_bouldering_hang.mp4` — Commons (bouldering) | 73 | `--freeze 24:49 --yaw -30 --ease --pivot-lock` | r3-200 | Y | `_r3` column = "holds"; pivot `0.50,0.45` `SBT:55` | N |
+
+**Do not propose** on the release ckpt: `sp_gym_tumble_r3` ("athlete dissolves f48, gone by f60"),
+`sp_judo_kick_r3` ("athlete walks off left, gone by f72"), `sp_polevault_bar_r3` ("vaulter flies off
+left at f36; by f48 vaulter, bar AND standards are gone"), `sp_hurdles_r3`, `sp_bboy_handstand_r3`
+("pose drifts during hold") — `SBT:53-60`. **Only `recambt` holds mid-motion plates (bt 4/9 vs 5c 0/9,
+`SBT:88-92`) and recambt is not the release checkpoint.** Also rejected: `y_spotweld_bullet`,
+`y_bikekick_orbit` (175 frames of a title card), `surf_orbit`, `skate_bullet`, `duplantis_bullet`,
+`dive_bullet` `SC:245-258`.
+
+---
+
+## E — stills
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| E paint 1 | `pa_anatomy_L` | `src/pa_anatomy.png` — PD painting (Rembrandt, *Anatomy Lesson*) | 243 | `--freeze 0:243 --yaw -34 --bounce --frames 243` | r3-200 | Y | "**Winners:** … babelc_L, anatomy_L, cardplayers_L …" `SC:342`; "every painting plate" is in the clean-243 f list `SV:407-420` | N |
+| E paint 2 | `pa_ambassadors_L` | `src/pa_ambassadors.png` — PD painting (Holbein) | 243 | `--freeze 0:243 --yaw -34 --bounce --frames 243` | r3-200 | Y | same Winners line `SC:342`; "`_L` … where both exist the long one is better" `SC:344` | N |
+| E paint 3 | `y_cafe_pushL` | `src/pa_cafe.png` — PD painting (Van Gogh, *Café Terrace*) | 243 | `--pivot 0.50,0.50 --pivot-lock --freeze 0:243 --dolly 0.60 --zoom 1 --ease --frames 243` | r3-200 | Y | "cafe" in the Winners line `SC:342`; the push arm, coverage 1.000 — a one-point-perspective painting is the `push` class `SV:427` | N |
+| E statue 1 | `hl_whaleskel_L` | `src/hl_whaleskel.png` — Commons (NHM Hintze Hall blue whale) | 243 | `--freeze 0:243 --yaw -27 --bounce --frames 243` | r3-200 | Y | "**best of set** … walls continue behind the camera" `SV:222`; one of "the two best single renders" `SC:15` | N |
+| E statue 2 | `sc_laocoon_L` | `src/sc_laocoon.png` — Commons (Laocoön group) | 243 | `--freeze 0:243 --yaw -34 --bounce --frames 243` | r3-200 | Y | sculptures orbit cleanly at 25–30° `SC:12`; "highest-yield class is **`op` orbit around a single museum object on a plain floor**" `SV:424` | N |
+| E statue 3 (alt) | `st_david_L` | `src/st_david.png` — Commons (Michelangelo's David) | 243 | `--freeze 0:243 --yaw -47 --bounce --frames 243` | r3-200 | Y | coverage 0.541 is **not** a reject: "Coverage measures how much the model had to invent, not how well it invented it" `SC:448` | N |
+| E photo 1 | `pd_iwojima_l_L` | `src/pd_iwojima.png` — PD photo (Rosenthal, Iwo Jima) | 243 | `--freeze 0:243 --yaw 40 --bounce --frames 243` | r3-200 | Y | "73 f, stills (aldrin / david / nave): equal to slightly better. No regression anywhere." `NVT:154`; coverage 0.884 | N |
+| E photo 2 | `pd_aldrin_l_L` | `src/pd_aldrin.png` — PD photo (NASA, Aldrin on the Moon) | 243 | `--freeze 0:243 --yaw 40 --bounce --frames 243` | r3-200 | Y | same `NVT:154`; a single dominant near subject on a plain ground plane | N |
+| E landmark 1 | `cp_library_push_L` | `src/dp_library.png` — Commons (library stacks) | 243 | `--pivot 0.5,0.5 --pivot-lock --freeze 0:243 --dolly 0.63 --zoom 1 --ease --frames 243` | r3-200 | Y | named in the clean-243 f list `SV:407-420`; coverage 0.998; corridor plates take `push`, never orbit `SV:109` | N |
+| E landmark 2 | `cp_neonalley_push_L` | `src/t0_neonalley.png` — Commons (neon alley) | 243 | `--pivot 0.5,0.55 --pivot-lock --freeze 0:243 --dolly 0.63 --zoom 1 --ease --frames 243` | r3-200 | Y | named in the clean-243 f list `SV:407-420`; coverage 0.994 | N |
+| E landmark 3 | `a2_s02_hf` | `inbox/a2_s02_hf.mp4` — Asia tour comparison plate | 73 | `--follow --start 0 --frames 73 --smooth 8 --canvas 1920x1088 --full 1920` | r3-200 | Y | "we track their path closely on every shot and are visibly *sharper* on **s02** (ridgelines, grass, prayer flags)" `AT2:79-83`; coverage 0.920 | N |
+| E landmark 4 (alt) | `at_s11_f3` | `inbox/at_s11_ph.mp4` — Americas tour comparison plate | 141 | `--follow --start 0 --frames 141 --smooth 8 --canvas 1920x1088 --full 1920` | r3-200 | Y | best of the Americas group, coverage 0.949 `ATL:48-51`; any pre-2026-09-06 `at_sNN` had delogo smearing and was rebuilt `ATL:180-193` | N |
+
+**Do not propose** from the hand-picked 243 f set: **`ic_siq_deep_L`** ("ends nose-first against a blank
+sandstone wall" `SV:407-420`; the Siq and Treasury are never in frame `SC:306`) and **`g_hkdino_push_L`**
+("travels straight past the dinosaur skeleton and finishes on an empty stairwell" `SV:407-420`) — both
+are in the brief's list but are recorded failures. Also skip `a2_s04_hf`/`a2_s05_hf` for a hero cut
+(0.700/0.693, "the 0.60–0.75 gamble band; expect softness there" `AT2:81`) unless the sharpness claim
+is the point.
+
+---
+
+## F — stereo / anaglyph (`--truck` constant offset = the right eye; no ramp flag on purpose)
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| F best | `st3_fh1` | `src/fh_w1.mp4` — Figure Helix sorting (robot-company reel) | 175 | `--truck 0.04 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "**最好的一块**:边比 0.02 宽一倍,仍能融合",stereoqa gain .95 / corr .89 `R:2500` | N |
+| F | `st3_pi1` | `src/pi_w1.mp4` — π0.5 folding | 175 | `--truck 0.04 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "干净,视差还有余量" .74/.73 `R:2499` | N |
+| F | `st3_at1` | `src/at_w1.mp4` — Boston Dynamics Atlas | 175 | `--truck 0.04 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "可融合" .70/.49 `R:2502` | N |
+
+Recipe notes: the **absence of a ramp flag is the mechanism** (`ramp ≡ 1` ⇒ constant lateral offset
+= the right eye, `IV:110-113`). Baseline scales **downward only**: `truck' = 0.04 × (0.018 × width / |dx|)`
+`R:2508`. **Do not propose** `st3_un3` ("0.02 / 0.04 都拒,这块板子不做立体" `R:2503`) or `st3_ap2`
+("板子含硬切,作废" `R:2505`; `ap2_w1` has a hard cut at f9–17 so every `ap2` job needs `--start 30`
+*and* a re-picked pivot, `R:2489`). `nx_w1` needs 0.02, not 0.04 `R:2498`.
+
+---
+
+## G — limitations (honest failures with a documented cause)
+
+| slot | job name | plate (origin) | frames | args | ckpt | out.mp4? | why | needs new job? |
+|---|---|---|---|---|---|---|---|---|
+| G1 pivot on background | `rv_dgc_xgP` | `src/dg_w2c.mp4` — Agility Digit (robot-company reel) | 124 | `--yaw 90 --sweep --freeze 0:124 --pivot-lock --start 0 --frames 124 --canvas 1920x1088 --full 1920` | r3-200 | Y | "**失败**:pivot 落在背景墙上,轨道半径巨大,Digit 25% 处出画,后面全是编出来的空仓库" `R:2643`; pivot `0.64,0.28`. Pair with the **fix** `rv_dgc2_xgP` (pivot `0.47,0.42`, same args) — "Digit 全程居中" `R:2644`: same plate, same move, only the pivot changed | N (ship both) |
+| G2 amplitude wall | `rv_nx1_yaw105` | `src/nx_w1.mp4` — 1X NEO | 175 | `--yaw 105 --pivot-lock --start 0 --frames 175 --canvas 1920x1088 --full 1920` | r3-200 | Y | "**报废** —— 两个机器人融成一坨,手臂重影漂浮" while `rv_nx1_yaw90`, which has the **larger** hole (57.24% vs 53.48%), is "好" `R:1219-1220`. hole% turns around past the wall and speckle% saturates at 59% on both, so **no metric finds the wall** `R:1227-1232` | N (ship `rv_nx1_yaw90` alongside as the control) |
+| G3 pull-back ceiling | `catpool_s_pull22` | `/home/chenyun/cat2.mp4` — user footage | 73 | `--frames 73 --sweep --ease --dolly 2.2 --zoom 1 --pivot-lock` | r3-200 | Y | at 1.8 the ladder is still clean (cov 0.630); at 2.2 "an invented pillar lands dead-centre, half-occluding the subject" (cov 0.558). The failure is **invented architecture, not blur** `SV:544-556` | N (ship `catpool_s_pull18` as the last clean rung) |
+| G4 wrong added axis on a pull | `rp_christ_pulltruck` | `src/st_christ.png` — Commons (Christ the Redeemer) | 124 | `--dolly 1.50 --zoom 1 --truck 0.20 --freeze 0:124 --start 0 --frames 124 --canvas 1184x1760 --full 1920` | r3-200 | Y | "statue **entirely gone**, a pedestal stub on empty mountainside"; `rp_christ_pulltruck_lock` fails pixel-identically ⇒ **`--pivot-lock` does not fix it**, and coverage is *inverted* here (0.710 broken vs 0.480 best). Rule: "on a pull-back, the added axis must be `--yaw`" `SV:620-649` — ship `rp_christ_pullyaw24` as the working twin | N |
+
+Alternate G rows if a non-robot failure is wanted: `w9fix_apollo_r28` ("烟雾里 VGGT 没有几何 … 别下 yaw"
+`R:2732`) or `rv_nx1_bu035a` (a constant +0.35 boom is **REFUSED as a whole, seed-independent**; the fix
+is `--sweep --ease` `R:2825,2836-2845`).
+
+---
+
+## Gaps the human should know about
+
+- **No shot table or build script exists** for `howitworks.mp4`, `showcase_v3`, `reel_wonders`,
+ `reel_paint`, `reel_icons`, `reel_sports`, `reel_yt1`, `orbit_quad`, `quarter_nx1`, `moves_pi` —
+ only the index lines in `R:8-30`. Slot C's three takes are a reconstruction, not a recovered list.
+- **Job-name reuse**: `y_dunk13_bullet2`, `y_maroney_bullet2`, `y_dupslow_bullet2` each appear twice in
+ the corpus with different `--start`/pivot, so `out//` holds whichever ran last. Re-render from
+ the job line you choose, do not trust the directory.
+- **`--pivot fx,fy` vs the 3rd field**: most rows carry the pivot in field 3, a few (`y_cafe_pushL`,
+ `cp_*_L`) repeat it inside the args. Keep both in sync when re-queuing.
+- Before any new `--pivot-lock` job, run `wm/pivcheck.py`: orbit radius = pivot depth, so a pivot on the
+ background flings the subject out of frame within a few frames, and `refuse.py` is blind to it (that is
+ exactly the G1 row). For a push, also check the fly-through `ahead` gauge (gate ≈ −0.1).
diff --git a/videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/out.mp4 b/videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..d8ce136cca902e3ed5a8f8674ab4f4392019dbd3
--- /dev/null
+++ b/videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:492a586d20dfe23b5ed5fa98981ed0e66ad3b1a7f3b9c115f31fa7a1c4687b58
+size 4529810
diff --git a/videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/source.mp4 b/videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..fb4a257283b8b1b3ecf165c6535ffa39e7c267b9
--- /dev/null
+++ b/videos-all/longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:44265b13cd4ab87e5a12f9830a16ec42be86e41033e9ada01b058e60cd87191e
+size 1540130
diff --git a/videos-all/longtake_showcase/TEASER_V4_NOTES.md b/videos-all/longtake_showcase/TEASER_V4_NOTES.md
new file mode 100644
index 0000000000000000000000000000000000000000..03458c1e3f0f08604f63a54e3a21ae8f8005aa5c
--- /dev/null
+++ b/videos-all/longtake_showcase/TEASER_V4_NOTES.md
@@ -0,0 +1,67 @@
+# Meridian — teaser v4 候选剪辑
+
+[观看 MP4](../teaser_meridian_showcase_v4.mp4) · [精确清单](teaser_v4/manifest.json) · [校验结果](teaser_v4/validation.json)
+
+**49.833 秒 / 1196 帧 / 1920 × 1080 / 24 fps / 无音轨。**
+
+仅新增成片、构建/检查脚本和本版本记录;网页、v3 及原素材均保留。这里的自然衔接指叙事、文案和剪辑节奏,不声称不同生成片段构成一次无缝生成。
+
+## 故事与取舍
+
+**控制时间 → 自由设计镜头路径 → 围绕运动中的主体改变视角 → 从照片与画作打开新视角。**
+
+| 段落 | 全片起点 | 帧数 / 时长 | 文案与处理 |
+| --- | --- | --- | --- |
+| 开头 | 0.000 s | 60 / 2.500 s | MERIDIAN — **A new perspective on space and time.** |
+| NBA | 2.500 s | 243 / 10.125 s | **An instant, revisited.** 保留动作、定格、恢复的完整过程及相应短句。 |
+| 复杂轨迹摩托 | 12.625 s | 243 / 10.125 s | **A path of your own.** 从后退、环绕到改变方向,最后让动作继续展开;使用所选 explained v2 的同一无字幕原始输出,不插入工程说明界面。 |
+| 彩粉 | 22.750 s | 175 / 7.292 s | **Move around. Move closer.** 完整环绕与推进;以腾空姿态接向芭蕾。 |
+| 芭蕾 | 30.042 s | 148 / 6.167 s | **A still image.** 真实输入 PNG 单独出现 1 秒,再切为 **A still image, another view.** 的输入/输出对比,完整播放 124 帧生成。 |
+| 《大使》 | 36.208 s | 267 / 11.125 s | **Even a painting.** 保留的输入画作先单独出现 1 秒,再切为 **Beyond the canvas.** 的输入/输出对比,完整播放 243 帧生成。 |
+| 结尾 | 47.333 s | 60 / 2.500 s | MERIDIAN — **One event. Any time. Anywhere.** |
+
+- 新增复杂轨迹摩托、彩粉和《大使》,保留 NBA 与芭蕾,共五个案例。
+- 暂不选 90° 摩托:与复杂轨迹摩托重复,后段右侧前轮明显抵达/越过下边缘。不是靠裁掉问题帧来声称整段质量通过。
+- 铺床、水母移出本版,避免功能和篇幅堆叠;Napoleon 由带保留输入与相机记录的《大使》替换。所有旧片仍在。
+- 不加章节编号、角度数值或轨迹图。复杂路径用三个可读的短句组呈现:**Make room. Move around. → Change direction. → Let it unfold.** 精确六阶段请求保留在清单中,不把请求角度当作实测生成运动。
+
+## 所选新素材
+
+以下路径相对 `videos-all/`:
+
+同名顶层 `meridian_grand_*.mp4` 带左下角相机轨迹叠加图,并非目录内 `out.mp4` 的字节相同副本;本版统一使用无叠加图的原始输出。
+
+- 摩托参考:`teaser_meridian_compound_motor_dust_explained_v2.mp4`。
+ - 其无字幕原始输出:`longtake_edit/multisegment/work_gpu5/takes/1789315608_4e9dd3_7/out.mp4`。
+ - 关联记录:[原 explained v2 清单](../longtake_edit/multisegment/motor_dust_margin_explainer_manifest.json)。使用全部 243 帧;主画面保留原生 1344 × 768,不放大。
+- 彩粉:`meridian_grand_l150_powder_orbit45_push85_175/out.mp4`,全部 175 帧。
+- 《大使》:`meridian_grand_t30_ambassadors_left_portrait_push60_lowertop243/out.mp4`,全部 243 帧。
+ - 展示的输入是 `pa_ambassadors_L/source.mp4` 的解码第 0 帧,导出为本版本的 `ambassadors_prepared_input.png`。
+ - 这是实际保留的 prepared input,不是生成输出首帧,也不冒充缺失的原始 PNG。确切图像复制来源仍不可考。
+
+## 合成与校验边界
+
+- 所选生成镜头均从原始输出直接合成,不读取已压制 teaser 来二次剪接。不裁切、不放大、不插帧、不改变输出播放速度、不在生成镜头间叠化、不做修复,也无新推理。
+- 仅缩小适配 1080p 画布。静态图像引入与随后双栏展示有明确布局切换;补齐时间轴的隐藏帧不出现在可见生成片段中。
+- CPU FFmpeg / H.264 CRF 15 / medium / yuv420p;编码和复杂滤镜各限 2 线程。
+- 构建时完整解码各段和成片,检查 24 fps、逐帧 PTS、无音轨及拼接前后解码帧哈希一致。
+- 独立检查逐帧比较五个生成画面与对应原始帧,检查两组输入图片的全部展示帧,并核对旧文件和所选原素材哈希。报告中的像素比较允许缩小和有损编码误差,不表示编码字节相同。
+- [构图总览](teaser_v4/composition_overview.jpg) 与 [片段衔接样本](teaser_v4/story_transitions.jpg) 用于静态审阅。具体人工查看范围记录在清单;**不将解码、数值对比或联系表审阅称为连续播放视觉验收。**
+
+从当前项目目录检查现有成片:
+
+```bash
+/home/chenyun/miniforge3/envs/wan_new/bin/python release_recam/videos-all/longtake_showcase/check_teaser_v4.py
+```
+
+`build_teaser_v4.py` 拒绝覆盖已有成片或分段。修改下一版时,另设版本名并同步脚本中的工作目录、输出名、分段路径和检查断言;不要覆盖 v3/v4。
+
+## 已知画面问题与来源限制
+
+- 摩托的轮辐、前叉和远景仍有软化或推断细节;源片与生成片的尘土和姿态可不同。
+- 彩粉的墙面/地面倾斜,后段远景有推断结构;上方粉末和下方垫子可能出边,不能据此宣称完整跳跃/落地过程。
+- 芭蕾会补出舞台细节并改变细小肢体轮廓。《大使》推进时出现窄的推断顶部区域,脸、手和器物仍是生成解释,不是恢复的历史空间。
+- 摩托和彩粉来源记录:Jacob + Katie Schwarz / Mystery Box,2014;详见[本地源片记录](../overnight/research/phantom_sports_source.json)。记录保留版权声明,未建立公开宣传许可。
+- NBA、芭蕾来源与限制沿用 [PREVIEW_NOTES.md](PREVIEW_NOTES.md)。《大使》仅有保留的画作输入导出;不因画作年代推断该复制图像的授权状况。
+
+**本地研究剪辑,非公开发布授权已齐备的成片。**
diff --git a/videos-all/longtake_showcase/TEASER_V5_NOTES.md b/videos-all/longtake_showcase/TEASER_V5_NOTES.md
new file mode 100644
index 0000000000000000000000000000000000000000..f1612a287a1beeb964843eb14e9eeea238b83eed
--- /dev/null
+++ b/videos-all/longtake_showcase/TEASER_V5_NOTES.md
@@ -0,0 +1,61 @@
+# Meridian — teaser v5
+
+[观看 MP4](../teaser_meridian_showcase_v5.mp4) · [精确清单](teaser_v5/manifest.json) · [校验结果](teaser_v5/validation.json)
+
+**49.042 秒 / 1177 帧 / 1920 × 1080 / 24 fps / 无音轨。**
+
+按确认意见恢复机器人多机位与原版拿破仑;保留 v4 的复杂轨迹摩托、彩粉与芭蕾。v3、v4、网页和原素材不覆盖。
+
+## 本次改动
+
+- **机器人:左侧主生成机位 + 右上实际模型输入 + 右中/右下两个生成机位。** 右上标注 `Model input`,替代原来的 `bed_arc`,不是把某个生成视角误标成输入。
+- 四格完整播放 175 帧,严格按同一 prepared-input 帧号 0–174 合成。它们不是同一场景的真实同步多机拍摄;生成视角独立推理,细小布料、手部形状仍可能不一致。
+- **画作恢复原版拿破仑**:`Beyond the canvas.` 下完整展示原有 73 帧竖幅视频,移除《大使》的输入图引入与双栏比较。不拿生成首帧冒充缺失的原画输入。
+- 不新增推理,不修补生成瑕疵,不插帧、不变速、不裁切、不放大;沿用简洁硬切和统一标题。自然衔接指故事与剪辑,而非一次无缝生成。
+
+## 故事顺序
+
+| 段落 | 全片起点 | 帧数 / 时长 | 文案 |
+| --- | --- | --- | --- |
+| 开头 | 0.000 s | 60 / 2.500 s | MERIDIAN — **A new perspective on space and time.** |
+| NBA | 2.500 s | 243 / 10.125 s | **An instant, revisited.** 动作 → 定格 → 恢复。 |
+| 机器人多机位 | 12.625 s | 175 / 7.292 s | **One event. Many perspectives.** 同一输入,多种视角。 |
+| 复杂轨迹摩托 | 19.917 s | 243 / 10.125 s | **A path of your own.** 后退、环绕、改变方向。 |
+| 彩粉 | 30.042 s | 175 / 7.292 s | **Move around. Move closer.** 环绕与推进,腾空姿态接芭蕾。 |
+| 芭蕾 | 37.333 s | 148 / 6.167 s | **A still image.** 真实输入图 24 帧,再以 **A still image, another view.** 展示输入与完整 124 帧生成。 |
+| 拿破仑 | 43.500 s | 73 / 3.042 s | **Beyond the canvas.** 原版竖幅画作视频。 |
+| 结尾 | 46.542 s | 60 / 2.500 s | MERIDIAN — **One event. Any time. Anywhere.** |
+
+## 恢复素材
+
+以下路径相对 `videos-all/`:
+
+- 机器人左侧:`meridian_longtake_l150_bed_crane32_175/out.mp4`。
+- 机器人右上实际模型输入:`teaser_v2/plates/bed.mp4`。这是保留的共同 prepared input,不是各机位的中间 `source.mp4`,也不声称是未经处理的原始拍摄文件。
+- 机器人右中:`meridian_v2_bed_cross_reveal/out.mp4`。
+- 机器人右下:`meridian_v2_bed_reverse_reveal/out.mp4`。
+- 拿破仑:`longtake_showcase/preview_assets/napoleon.mp4`。与原版本同一素材;输入画作、生成配方及相机记录未提供,详见 [素材清单](preview_assets/napoleon.json)。
+
+摩托、彩粉与芭蕾的选择及来源沿用 [v4 记录](TEASER_V4_NOTES.md)。不使用带轨迹叠加图的顶层 `meridian_grand_*.mp4` 代替无叠加图的 `out.mp4`。90° 摩托、水母和《大使》不在本版中,旧素材均保留。
+
+## 校验与审阅
+
+- CPU FFmpeg / H.264 CRF 15 / medium / yuv420p,缩小适配 1080p 画布;编码与复杂滤镜各限 2 线程。
+- 构建与独立检查执行完整解码、24 fps、逐帧 PTS、无音轨、分段与最终拼接解码帧哈希一致性检查。
+- 独立逐帧比较所有可见视频区域与对应素材帧,包含机器人的全部四格;芭蕾输入图的全部展示帧也比较。允许 Lanczos 缩小及有损编码误差(亮度 MSE < 10),不声称编码字节与素材一致。
+- [旧文件哈希快照](teaser_v5/preserved_hashes.json) 覆盖旧版本、网页及相关输入;校验脚本核对未被修改。
+- [构图总览](teaser_v5/composition_overview.jpg) 与 [切点样本](teaser_v5/story_transitions.jpg) 仅用于静态审阅。实际查看范围记录在清单,**不将逐帧数值检查或联系表审阅称为连续播放视觉验收**。
+
+从项目根目录检查:
+
+```bash
+/home/chenyun/miniforge3/envs/wan_new/bin/python release_recam/videos-all/longtake_showcase/check_teaser_v5.py
+```
+
+`build_teaser_v5.py` 拒绝覆盖现有成片或分段;后续修改请使用新版本名。
+
+## 保留的限制
+
+摩托轮辐、前叉和远景有软化/推断细节;彩粉的墙面、地面倾斜,边缘粉末与垫子可能出框,未呈现完整落地。芭蕾和拿破仑展示的是生成解释,不是历史空间的真实恢复。机器人输入时间一致不保证各生成视角的细节或物理几何完全一致。
+
+来源与授权限制沿用 [PREVIEW_NOTES.md](PREVIEW_NOTES.md)、[v4 记录](TEASER_V4_NOTES.md) 和拿破仑素材清单。**仅本地研究剪辑,公开宣传许可尚未建立。**
diff --git a/videos-all/longtake_showcase/TEASER_V6_NOTES.md b/videos-all/longtake_showcase/TEASER_V6_NOTES.md
new file mode 100644
index 0000000000000000000000000000000000000000..83312fb5393345f9b250faae27ecca05af47d5bc
--- /dev/null
+++ b/videos-all/longtake_showcase/TEASER_V6_NOTES.md
@@ -0,0 +1,67 @@
+# Meridian — teaser v6
+
+[观看 MP4](../teaser_meridian_showcase_v6.mp4) · [精确清单](teaser_v6/manifest.json) · [校验结果](teaser_v6/validation.json)
+
+**48.042 秒 / 1153 帧 / 1920 × 1080 / 24 fps / 无音轨。**
+
+本版只新增成片、构建/检查脚本及版本记录,v3、v4、v5、网页和原素材均保留。
+
+## 确认后的五项调整
+
+1. **机器人不再标注 “Model input”。** 四格布局不变:左侧主生成机位,右上实际共同输入,右中/右下两个生成机位;全部按输入帧号 0–174 同步。
+2. **开场更简洁。** 黑底、暖白 MERIDIAN,手动统一字距并增大字号;首帧即有完整品牌标题。较小的衬线副标题在 0.2–1.0 秒间轻柔出现,无装饰线、图案或额外口号。
+3. **摩托加入输入与动态轨迹。** 左侧完整原生 1344 × 768 生成视频;右上输入视频;右下低对比的完整路径、暖金已走路径、亮色当前位置与朝向线框。只保留 `Input` / `Camera path` 两个小标题,无坐标轴、角度数值或工程面板。
+4. **芭蕾取消突兀的布局切换。** 删除单独大图展示的 24 帧,从第一帧到最后一帧固定为输入照片+生成视频。原有 124 帧生成完整保留,不加遮挡首帧的淡入、不插帧、不变速。
+5. 拿破仑标题改为 **“And beyond the canvas.”**,承接照片案例;仍完整展示原版 73 帧竖幅视频。
+
+## 故事顺序
+
+| 段落 | 全片起点 | 帧数 / 时长 | 文案 |
+| --- | --- | --- | --- |
+| 开头 | 0.000 s | 60 / 2.500 s | MERIDIAN — **A new perspective on space and time.** |
+| NBA | 2.500 s | 243 / 10.125 s | **An instant, revisited.** |
+| 机器人 | 12.625 s | 175 / 7.292 s | **One event. Many perspectives.** |
+| 摩托扬尘 | 19.917 s | 243 / 10.125 s | **A path of your own.** |
+| 彩粉 | 30.042 s | 175 / 7.292 s | **Move around. Move closer.** |
+| 芭蕾 | 37.333 s | 124 / 5.167 s | **A still image, another view.** |
+| 拿破仑 | 42.500 s | 73 / 3.042 s | **And beyond the canvas.** |
+| 结尾 | 45.542 s | 60 / 2.500 s | MERIDIAN — **One event. Any time. Anywhere.** |
+
+“自然衔接”指叙事与剪辑;案例之间仍是明确硬切,不声称是一次无缝生成。
+
+## 摩托输入与轨迹依据
+
+素材路径相对 `videos-all/longtake_edit/multisegment/`:
+
+- 参考记录:`motor_dust_margin_explainer_manifest.json`,对应用户所选 `teaser_meridian_compound_motor_dust_explained_v2.mp4`。
+- 生成视频:`work_gpu5/takes/1789315608_4e9dd3_7/out.mp4`。
+- 输入视频:`work_gpu5/takes/1789315608_4e9dd3_7/source.mp4`。这是该次生成保留的、按请求选帧的模型输入,不冒充未经处理的拍摄原片。
+- 相机数据:`motor_dust_sixphase_opposed35_wheelmargin_live243_seed3407/requested_cameras.npz`,使用全部 243 帧 `c2w_W` 的位置和旋转;位置除以记录的 `zm` 还原请求坐标。
+- 时间对应:输入小窗与输出按同一输出帧号 0–242 展示;其 prepared-input 帧号由实际 `tmap` 从 0 走到 174,重复选帧来自原始生成请求,未自行重新变速。
+- 与 `path_design.json`、`warp.json` 的时间映射交叉核对;`warp.json` 相机向量仅保留四位小数,位置/朝向交叉检查容差为 1e-4。可视化使用精度完整的 NPZ,不使用舍入后的 JSON 重建轨迹。
+- 图为真实请求数据的**固定斜视正交投影**:统一比例,不改写路径、不重新平滑、不伪造相机运动。当前位置与相机线框逐帧使用同一姿态。线框尺寸仅用于示意朝向,**不表示校准过的真实视场角**。
+- 轨迹不是从生成画面恢复的实测相机运动,也不保证生成结果完全遵守几何约束。精确投影、坐标、旋转、时间映射和来源哈希保存在 [轨迹清单](teaser_v6/camera_path.json)。
+
+## 构建与校验
+
+- CPU FFmpeg / H.264 CRF 15 / medium / yuv420p,编码与复杂滤镜各限 2 线程。轨迹中间素材为无损 H.264,最终按统一成片参数编码。
+- 对原视频只做缩小适配,无裁切、放大、插帧、修复或新推理。摩托主画面保持原生分辨率。
+- 完整解码分段与成片,检查 24 fps、逐帧 PTS、无音轨和最终拼接解码帧一致性。
+- 独立逐帧比较全部可见视频区域,包括机器人四格、摩托输出/输入/轨迹三块;芭蕾输入照片比较全部 124 帧。亮度 MSE < 10,允许缩小及有损编码误差,不声称素材和成片的编码字节相同。
+- 独立核对相机 NPZ 与绘图记录的所有位置、旋转、投影点和相机线框坐标,并检查每帧当前位置标记可见。检查机器人旧标签区域为空、开场标题首帧可见与副标题渐显、芭蕾从首帧固定布局。
+- [旧文件快照](teaser_v6/preserved_hashes.json) 核对旧版本、网页与相关素材未被修改。
+- [构图总览](teaser_v6/composition_overview.jpg) 和 [切点样本](teaser_v6/story_transitions.jpg) 仅供静态审阅。实际查看范围记录在清单;**不将数值校验或联系表审阅当作连续播放视觉验收**。
+
+从项目根目录检查现有成片:
+
+```bash
+/home/chenyun/miniforge3/envs/wan_new/bin/python release_recam/videos-all/longtake_showcase/check_teaser_v6.py
+```
+
+构建顺序为 `prepare_teaser_v6.py` → `build_teaser_v6.py` → `check_teaser_v6.py`。准备/构建脚本拒绝覆盖成片与资产;下一版应更换版本名。旧文件快照需在修改前建立,不能事后重建来声称旧文件未改动。
+
+## 既有限制
+
+镜头与来源限制沿用 [v5 记录](TEASER_V5_NOTES.md) 和 [v4 记录](TEASER_V4_NOTES.md):机器人独立生成视角的细节可能不一致;摩托轮辐、前叉与远景有软化/推断;彩粉有墙地倾斜、边缘出框及未完整落地;芭蕾和拿破仑包含生成解释。拿破仑的原始输入画作、配方和相机记录未提供。
+
+**本地研究剪辑,公开宣传许可尚未建立。**
diff --git a/videos-all/longtake_showcase/TEASER_V7_NOTES.md b/videos-all/longtake_showcase/TEASER_V7_NOTES.md
new file mode 100644
index 0000000000000000000000000000000000000000..86d3406bf426dcb272a877e451cbd5271a563bc1
--- /dev/null
+++ b/videos-all/longtake_showcase/TEASER_V7_NOTES.md
@@ -0,0 +1,53 @@
+# Meridian — teaser v7
+
+[观看 MP4](../teaser_meridian_showcase_v7.mp4) · [精确清单](teaser_v7/manifest.json) · [校验结果](teaser_v7/validation.json)
+
+**48.042 秒 / 1153 帧 / 1920 × 1080 / 24 fps / 无音轨。**
+
+只调整两处标题的出现节奏与拿破仑段文案,v6 的镜头、时长、布局和品牌尾卡保留。旧版本、网页及原素材不覆盖。
+
+## 文案与节奏
+
+### NBA — One moment. Revisited.
+
+- 第 0 帧即显示 **One moment.**,位置固定、暖白常规衬线体。
+- 输入时间从输出第 54 帧起定格;第 59 帧开始 **Revisited.** 的 6 帧淡入,第 65 帧完全显示,随后保留至本段结束。
+- 淡入从定格后 5 帧(约 0.21 秒)启动。没有新增视频定格:原有输入时间控制、生成视角运动和后续动作恢复均不改动。
+
+### 机器人 — One event. Many perspectives.
+
+- 第 0 帧显示 **One event.**。
+- 第 14 帧(约 0.58 秒)开始 **Many perspectives.** 的 6 帧淡入,第 20 帧完全显示。
+- 两句都保留前半句,后半句采用 **Nimbus Roman Bold / 暖金色 `#c5b48d`**,与摩托轨迹的金色呼应。
+- 两部分共用固定基线,字不移动、不跳动、不打字式逐字出现。机器人右上仍为实际输入,不加输入标签。
+
+### 拿破仑 — Beyond the frame.
+
+将 **And beyond the canvas.** 改为 **Beyond the frame.**,从单指画作扩展到视频、照片与画面边界。
+
+最终品牌尾卡保持 **One event. Any time. Anywhere.**,不替换为备选句。
+
+## 未变内容
+
+- 段落顺序、全部原视频帧、播放速度与时长沿用 [v6](TEASER_V6_NOTES.md)。
+- 开场设计、摩托输入+真实请求轨迹、彩粉、芭蕾固定双栏和最终品牌尾卡不改动。
+- `opening.png`、`camera_path.mp4` 是 v6 资产的字节相同副本;相机清单仅将视频引用更新为 v7 路径。没有新绘制轨迹或新推理。
+- 不裁切、不放大、不插帧,不在生成镜头之间叠化,不修补原有生成细节。
+
+## 检查与审阅
+
+- 完整解码各分段及最终成片,核对 24 fps、逐帧 PTS、无音轨和拼接前后解码帧一致。
+- 对所有视频区域逐帧与对应源帧比较,包括机器人四格及摩托三块;芭蕾输入图覆盖全部展示帧。允许缩小及 CRF15 有损编码误差(亮度 MSE < 10)。
+- 对 NBA 与机器人标题逐帧检查:后半句没有提前出现、6 帧渐显亮度递增、完全显示后保持稳定、金色实际像素符合目标色;前半句全程位置不变。
+- 验证开场、摩托、彩粉、芭蕾和尾卡分段与 v6 字节相同,核对 [旧文件快照](teaser_v7/preserved_hashes.json)。
+- 静态审阅:[两拍标题](teaser_v7/title_reveals.jpg)、[构图总览](teaser_v7/composition_overview.jpg)、[切点样本](teaser_v7/story_transitions.jpg)。实际查看范围记录在清单,**不冒充连续播放视觉验收**。
+
+从项目根目录检查成片:
+
+```bash
+/home/chenyun/miniforge3/envs/wan_new/bin/python release_recam/videos-all/longtake_showcase/check_teaser_v7.py
+```
+
+`build_teaser_v7.py` 使用本版本保留的开场/轨迹资产,并拒绝覆盖现有成片或分段;后续改版另设版本名,修改前保留旧文件哈希快照。
+
+来源、相机可视化边界和生成瑕疵说明沿用 [v6 记录](TEASER_V6_NOTES.md)。轨迹代表相机请求而非实测生成运动。**仅本地研究剪辑,公开宣传许可尚未建立。**
diff --git a/videos-all/longtake_showcase/teaser_v12/intro_059.jpg b/videos-all/longtake_showcase/teaser_v12/intro_059.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2793334a88ec2d100d4549b295ba50445037102e
Binary files /dev/null and b/videos-all/longtake_showcase/teaser_v12/intro_059.jpg differ
diff --git a/videos-all/longtake_showcase/teaser_v7/intro_059.jpg b/videos-all/longtake_showcase/teaser_v7/intro_059.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..9d107f969921c6d535b1d7bd2da4babc953ffa73
Binary files /dev/null and b/videos-all/longtake_showcase/teaser_v7/intro_059.jpg differ
diff --git a/videos-all/longtake_showcase/teaser_v7/manifest.json b/videos-all/longtake_showcase/teaser_v7/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..6c1547cb063eeb5f1835b8630737ef7a7d9c766e
--- /dev/null
+++ b/videos-all/longtake_showcase/teaser_v7/manifest.json
@@ -0,0 +1,2609 @@
+{
+ "file": "../teaser_meridian_showcase_v7.mp4",
+ "frames": 1153,
+ "fps": 24,
+ "seconds": 48.041666666666664,
+ "size": [
+ 1920,
+ 1080
+ ],
+ "sha256": "5ecdc6a8b86132313eff9455c6217a9428ae49fa7e1685b56f1f832ef00ed14d",
+ "bytes": 36223963,
+ "created_utc": "2026-09-13T19:49:28.930301+00:00",
+ "chapters": [
+ {
+ "key": "intro",
+ "title": "A new perspective on space and time.",
+ "start": 0,
+ "frames": 60,
+ "seconds": 2.5,
+ "segment": "teaser_v7/intro.mp4",
+ "inputs": [],
+ "copy": [
+ {
+ "text": "MERIDIAN",
+ "first": 0,
+ "last": 59
+ },
+ {
+ "text": "A new perspective on space and time.",
+ "first": 5,
+ "last": 59,
+ "fade_in_seconds": [
+ 0.2,
+ 1.0
+ ]
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 5,
+ 12,
+ 24,
+ 30,
+ 59
+ ]
+ },
+ {
+ "key": "nba",
+ "title": "One moment. Revisited.",
+ "start": 60,
+ "frames": 243,
+ "seconds": 10.125,
+ "segment": "teaser_v7/nba.mp4",
+ "inputs": [
+ {
+ "key": "nba",
+ "file": "../meridian_longtake_l150_nba3_sweep_right18/out.mp4",
+ "sha256": "0afc31525dee3c22ed39ec5593943788fa4f8ae0717a47e1dd4466a9d66d9af5",
+ "output_rect": [
+ 186,
+ 134,
+ 1548,
+ 878
+ ],
+ "first_frame": 0,
+ "last_frame": 242,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 123
+ ]
+ }
+ ],
+ "copy": [
+ {
+ "text": "One moment.",
+ "first": 0,
+ "last": 242
+ },
+ {
+ "text": "Revisited.",
+ "first": 60,
+ "last": 242,
+ "fade_frames": [
+ 59,
+ 65
+ ],
+ "color": "#c5b48d",
+ "weight": "bold"
+ },
+ {
+ "text": "Let it unfold.",
+ "first": 0,
+ "last": 53
+ },
+ {
+ "text": "Hold the moment.",
+ "first": 54,
+ "last": 173
+ },
+ {
+ "text": "Let it continue.",
+ "first": 174,
+ "last": 242
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 53,
+ 54,
+ 58,
+ 59,
+ 60,
+ 62,
+ 65,
+ 121,
+ 173,
+ 174,
+ 242
+ ],
+ "title_reveal": {
+ "prefix": "One moment.",
+ "emphasis": "Revisited.",
+ "fade_start": 59,
+ "fade_end": 65,
+ "cue": "Prepared-input time holds at output frame 54; emphasis fade starts five frames later.",
+ "prefix_x": 64,
+ "emphasis_x": 302,
+ "baseline_y": 100,
+ "font_size": 40,
+ "prefix_font": "/usr/share/fonts/opentype/urw-base35/NimbusRoman-Regular.otf",
+ "emphasis_font": "/usr/share/fonts/opentype/urw-base35/NimbusRoman-Bold.otf",
+ "prefix_color": "#eeeae1",
+ "emphasis_color": "#c5b48d"
+ }
+ },
+ {
+ "key": "bed",
+ "title": "One event. Many perspectives.",
+ "start": 303,
+ "frames": 175,
+ "seconds": 7.291666666666667,
+ "segment": "teaser_v7/bed.mp4",
+ "inputs": [
+ {
+ "key": "bed_main",
+ "file": "../meridian_longtake_l150_bed_crane32_175/out.mp4",
+ "sha256": "ec431fe2bbca933fd858b45e5db9025585f6b59431e5ed2d78d5217f5de833ea",
+ "role": "generated",
+ "output_rect": [
+ 66,
+ 212,
+ 1322,
+ 750
+ ],
+ "first_frame": 0,
+ "last_frame": 174,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 125,
+ 126,
+ 127,
+ 128,
+ 129,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ 140,
+ 141,
+ 142,
+ 143,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 151,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 157,
+ 158,
+ 159,
+ 160,
+ 161,
+ 162,
+ 163,
+ 164,
+ 165,
+ 166,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 174
+ ]
+ },
+ {
+ "key": "bed_input",
+ "file": "../teaser_v2/plates/bed.mp4",
+ "sha256": "441ebcb70944075c795dead0123f2485bba209aa2789621556793a6cacdbad07",
+ "role": "model_input",
+ "output_rect": [
+ 1428,
+ 212,
+ 412,
+ 234
+ ],
+ "first_frame": 0,
+ "last_frame": 174,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 125,
+ 126,
+ 127,
+ 128,
+ 129,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ 140,
+ 141,
+ 142,
+ 143,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 151,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 157,
+ 158,
+ 159,
+ 160,
+ 161,
+ 162,
+ 163,
+ 164,
+ 165,
+ 166,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 174
+ ]
+ },
+ {
+ "key": "bed_cross",
+ "file": "../meridian_v2_bed_cross_reveal/out.mp4",
+ "sha256": "dfbf6c60344d76ef56e0fd114321968c428a68017f08350d0addc1764f37b3f8",
+ "role": "generated",
+ "output_rect": [
+ 1428,
+ 470,
+ 412,
+ 234
+ ],
+ "first_frame": 0,
+ "last_frame": 174,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 125,
+ 126,
+ 127,
+ 128,
+ 129,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ 140,
+ 141,
+ 142,
+ 143,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 151,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 157,
+ 158,
+ 159,
+ 160,
+ 161,
+ 162,
+ 163,
+ 164,
+ 165,
+ 166,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 174
+ ]
+ },
+ {
+ "key": "bed_reverse",
+ "file": "../meridian_v2_bed_reverse_reveal/out.mp4",
+ "sha256": "bb8f8f2e7576860e5b7db808c7715bcc00a26f607f6e4a7880fd4c9b36fa4061",
+ "role": "generated",
+ "output_rect": [
+ 1428,
+ 728,
+ 412,
+ 234
+ ],
+ "first_frame": 0,
+ "last_frame": 174,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 125,
+ 126,
+ 127,
+ 128,
+ 129,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ 140,
+ 141,
+ 142,
+ 143,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 151,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 157,
+ 158,
+ 159,
+ 160,
+ 161,
+ 162,
+ 163,
+ 164,
+ 165,
+ 166,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 174
+ ]
+ }
+ ],
+ "copy": [
+ {
+ "text": "One event.",
+ "first": 0,
+ "last": 174
+ },
+ {
+ "text": "Many perspectives.",
+ "first": 15,
+ "last": 174,
+ "fade_frames": [
+ 14,
+ 20
+ ],
+ "color": "#c5b48d",
+ "weight": "bold"
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 13,
+ 14,
+ 15,
+ 17,
+ 20,
+ 87,
+ 174
+ ],
+ "title_reveal": {
+ "prefix": "One event.",
+ "emphasis": "Many perspectives.",
+ "fade_start": 14,
+ "fade_end": 20,
+ "cue": "Emphasis fade starts after 14 frames, approximately 0.6 seconds.",
+ "prefix_x": 64,
+ "emphasis_x": 254,
+ "baseline_y": 100,
+ "font_size": 40,
+ "prefix_font": "/usr/share/fonts/opentype/urw-base35/NimbusRoman-Regular.otf",
+ "emphasis_font": "/usr/share/fonts/opentype/urw-base35/NimbusRoman-Bold.otf",
+ "prefix_color": "#eeeae1",
+ "emphasis_color": "#c5b48d"
+ },
+ "synchronization": "All four panels show the same prepared-input frame index 0\u2013174; top right is the shared actual model input, not a generated view."
+ },
+ {
+ "key": "motor",
+ "title": "A path of your own.",
+ "start": 478,
+ "frames": 243,
+ "seconds": 10.125,
+ "segment": "teaser_v7/motor.mp4",
+ "inputs": [
+ {
+ "key": "motor",
+ "file": "../longtake_edit/multisegment/work_gpu5/takes/1789315608_4e9dd3_7/out.mp4",
+ "sha256": "83cf02ebf7430d284beb7e1581fc8e003587991b1abe8d53d853949c34ba4057",
+ "role": "generated",
+ "output_rect": [
+ 64,
+ 180,
+ 1344,
+ 768
+ ],
+ "first_frame": 0,
+ "last_frame": 242,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 1,
+ 2,
+ 3,
+ 4,
+ 4,
+ 5,
+ 6,
+ 6,
+ 7,
+ 8,
+ 9,
+ 9,
+ 10,
+ 11,
+ 12,
+ 12,
+ 13,
+ 14,
+ 14,
+ 15,
+ 16,
+ 17,
+ 17,
+ 18,
+ 19,
+ 19,
+ 20,
+ 21,
+ 22,
+ 22,
+ 23,
+ 24,
+ 24,
+ 25,
+ 26,
+ 27,
+ 27,
+ 28,
+ 29,
+ 30,
+ 30,
+ 31,
+ 32,
+ 32,
+ 33,
+ 34,
+ 35,
+ 35,
+ 36,
+ 37,
+ 38,
+ 38,
+ 39,
+ 40,
+ 41,
+ 41,
+ 42,
+ 43,
+ 43,
+ 44,
+ 45,
+ 45,
+ 46,
+ 47,
+ 48,
+ 48,
+ 49,
+ 50,
+ 50,
+ 51,
+ 52,
+ 52,
+ 53,
+ 54,
+ 54,
+ 55,
+ 56,
+ 57,
+ 57,
+ 58,
+ 59,
+ 59,
+ 60,
+ 61,
+ 61,
+ 62,
+ 63,
+ 64,
+ 64,
+ 65,
+ 66,
+ 67,
+ 67,
+ 68,
+ 69,
+ 70,
+ 70,
+ 71,
+ 72,
+ 72,
+ 73,
+ 74,
+ 75,
+ 75,
+ 76,
+ 77,
+ 78,
+ 78,
+ 79,
+ 80,
+ 80,
+ 81,
+ 82,
+ 83,
+ 83,
+ 84,
+ 85,
+ 86,
+ 86,
+ 87,
+ 88,
+ 89,
+ 89,
+ 90,
+ 91,
+ 92,
+ 92,
+ 93,
+ 94,
+ 94,
+ 95,
+ 96,
+ 97,
+ 97,
+ 98,
+ 99,
+ 100,
+ 100,
+ 101,
+ 102,
+ 103,
+ 103,
+ 104,
+ 105,
+ 105,
+ 106,
+ 107,
+ 108,
+ 108,
+ 109,
+ 110,
+ 110,
+ 111,
+ 112,
+ 112,
+ 113,
+ 114,
+ 115,
+ 115,
+ 116,
+ 117,
+ 117,
+ 118,
+ 119,
+ 120,
+ 120,
+ 121,
+ 122,
+ 122,
+ 123,
+ 124,
+ 125,
+ 125,
+ 126,
+ 127,
+ 127,
+ 128,
+ 129,
+ 130,
+ 130,
+ 131,
+ 132,
+ 132,
+ 133,
+ 134,
+ 134,
+ 135,
+ 136,
+ 137,
+ 137,
+ 138,
+ 139,
+ 139,
+ 140,
+ 141,
+ 142,
+ 142,
+ 143,
+ 144,
+ 145,
+ 145,
+ 146,
+ 147,
+ 147,
+ 148,
+ 149,
+ 150,
+ 150,
+ 151,
+ 152,
+ 153,
+ 153,
+ 154,
+ 155,
+ 155,
+ 156,
+ 157,
+ 158,
+ 158,
+ 159,
+ 160,
+ 160,
+ 161,
+ 162,
+ 163,
+ 163,
+ 164,
+ 165,
+ 165,
+ 166,
+ 167,
+ 168,
+ 168,
+ 169,
+ 170,
+ 170,
+ 171,
+ 172,
+ 173,
+ 173,
+ 174
+ ]
+ },
+ {
+ "key": "motor_input",
+ "file": "../longtake_edit/multisegment/work_gpu5/takes/1789315608_4e9dd3_7/source.mp4",
+ "sha256": "44265b13cd4ab87e5a12f9830a16ec42be86e41033e9ada01b058e60cd87191e",
+ "role": "model_input",
+ "output_rect": [
+ 1440,
+ 180,
+ 416,
+ 236
+ ],
+ "first_frame": 0,
+ "last_frame": 242,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 1,
+ 2,
+ 3,
+ 4,
+ 4,
+ 5,
+ 6,
+ 6,
+ 7,
+ 8,
+ 9,
+ 9,
+ 10,
+ 11,
+ 12,
+ 12,
+ 13,
+ 14,
+ 14,
+ 15,
+ 16,
+ 17,
+ 17,
+ 18,
+ 19,
+ 19,
+ 20,
+ 21,
+ 22,
+ 22,
+ 23,
+ 24,
+ 24,
+ 25,
+ 26,
+ 27,
+ 27,
+ 28,
+ 29,
+ 30,
+ 30,
+ 31,
+ 32,
+ 32,
+ 33,
+ 34,
+ 35,
+ 35,
+ 36,
+ 37,
+ 38,
+ 38,
+ 39,
+ 40,
+ 41,
+ 41,
+ 42,
+ 43,
+ 43,
+ 44,
+ 45,
+ 45,
+ 46,
+ 47,
+ 48,
+ 48,
+ 49,
+ 50,
+ 50,
+ 51,
+ 52,
+ 52,
+ 53,
+ 54,
+ 54,
+ 55,
+ 56,
+ 57,
+ 57,
+ 58,
+ 59,
+ 59,
+ 60,
+ 61,
+ 61,
+ 62,
+ 63,
+ 64,
+ 64,
+ 65,
+ 66,
+ 67,
+ 67,
+ 68,
+ 69,
+ 70,
+ 70,
+ 71,
+ 72,
+ 72,
+ 73,
+ 74,
+ 75,
+ 75,
+ 76,
+ 77,
+ 78,
+ 78,
+ 79,
+ 80,
+ 80,
+ 81,
+ 82,
+ 83,
+ 83,
+ 84,
+ 85,
+ 86,
+ 86,
+ 87,
+ 88,
+ 89,
+ 89,
+ 90,
+ 91,
+ 92,
+ 92,
+ 93,
+ 94,
+ 94,
+ 95,
+ 96,
+ 97,
+ 97,
+ 98,
+ 99,
+ 100,
+ 100,
+ 101,
+ 102,
+ 103,
+ 103,
+ 104,
+ 105,
+ 105,
+ 106,
+ 107,
+ 108,
+ 108,
+ 109,
+ 110,
+ 110,
+ 111,
+ 112,
+ 112,
+ 113,
+ 114,
+ 115,
+ 115,
+ 116,
+ 117,
+ 117,
+ 118,
+ 119,
+ 120,
+ 120,
+ 121,
+ 122,
+ 122,
+ 123,
+ 124,
+ 125,
+ 125,
+ 126,
+ 127,
+ 127,
+ 128,
+ 129,
+ 130,
+ 130,
+ 131,
+ 132,
+ 132,
+ 133,
+ 134,
+ 134,
+ 135,
+ 136,
+ 137,
+ 137,
+ 138,
+ 139,
+ 139,
+ 140,
+ 141,
+ 142,
+ 142,
+ 143,
+ 144,
+ 145,
+ 145,
+ 146,
+ 147,
+ 147,
+ 148,
+ 149,
+ 150,
+ 150,
+ 151,
+ 152,
+ 153,
+ 153,
+ 154,
+ 155,
+ 155,
+ 156,
+ 157,
+ 158,
+ 158,
+ 159,
+ 160,
+ 160,
+ 161,
+ 162,
+ 163,
+ 163,
+ 164,
+ 165,
+ 165,
+ 166,
+ 167,
+ 168,
+ 168,
+ 169,
+ 170,
+ 170,
+ 171,
+ 172,
+ 173,
+ 173,
+ 174
+ ]
+ },
+ {
+ "key": "camera_path",
+ "file": "teaser_v7/camera_path.mp4",
+ "sha256": "4035a1288568cc7560e5eac40db1cbfec83ef049a2fcd68d9c2f10a6ac467831",
+ "role": "visualization",
+ "output_rect": [
+ 1440,
+ 516,
+ 416,
+ 432
+ ],
+ "first_frame": 0,
+ "last_frame": 242,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 1,
+ 2,
+ 3,
+ 4,
+ 4,
+ 5,
+ 6,
+ 6,
+ 7,
+ 8,
+ 9,
+ 9,
+ 10,
+ 11,
+ 12,
+ 12,
+ 13,
+ 14,
+ 14,
+ 15,
+ 16,
+ 17,
+ 17,
+ 18,
+ 19,
+ 19,
+ 20,
+ 21,
+ 22,
+ 22,
+ 23,
+ 24,
+ 24,
+ 25,
+ 26,
+ 27,
+ 27,
+ 28,
+ 29,
+ 30,
+ 30,
+ 31,
+ 32,
+ 32,
+ 33,
+ 34,
+ 35,
+ 35,
+ 36,
+ 37,
+ 38,
+ 38,
+ 39,
+ 40,
+ 41,
+ 41,
+ 42,
+ 43,
+ 43,
+ 44,
+ 45,
+ 45,
+ 46,
+ 47,
+ 48,
+ 48,
+ 49,
+ 50,
+ 50,
+ 51,
+ 52,
+ 52,
+ 53,
+ 54,
+ 54,
+ 55,
+ 56,
+ 57,
+ 57,
+ 58,
+ 59,
+ 59,
+ 60,
+ 61,
+ 61,
+ 62,
+ 63,
+ 64,
+ 64,
+ 65,
+ 66,
+ 67,
+ 67,
+ 68,
+ 69,
+ 70,
+ 70,
+ 71,
+ 72,
+ 72,
+ 73,
+ 74,
+ 75,
+ 75,
+ 76,
+ 77,
+ 78,
+ 78,
+ 79,
+ 80,
+ 80,
+ 81,
+ 82,
+ 83,
+ 83,
+ 84,
+ 85,
+ 86,
+ 86,
+ 87,
+ 88,
+ 89,
+ 89,
+ 90,
+ 91,
+ 92,
+ 92,
+ 93,
+ 94,
+ 94,
+ 95,
+ 96,
+ 97,
+ 97,
+ 98,
+ 99,
+ 100,
+ 100,
+ 101,
+ 102,
+ 103,
+ 103,
+ 104,
+ 105,
+ 105,
+ 106,
+ 107,
+ 108,
+ 108,
+ 109,
+ 110,
+ 110,
+ 111,
+ 112,
+ 112,
+ 113,
+ 114,
+ 115,
+ 115,
+ 116,
+ 117,
+ 117,
+ 118,
+ 119,
+ 120,
+ 120,
+ 121,
+ 122,
+ 122,
+ 123,
+ 124,
+ 125,
+ 125,
+ 126,
+ 127,
+ 127,
+ 128,
+ 129,
+ 130,
+ 130,
+ 131,
+ 132,
+ 132,
+ 133,
+ 134,
+ 134,
+ 135,
+ 136,
+ 137,
+ 137,
+ 138,
+ 139,
+ 139,
+ 140,
+ 141,
+ 142,
+ 142,
+ 143,
+ 144,
+ 145,
+ 145,
+ 146,
+ 147,
+ 147,
+ 148,
+ 149,
+ 150,
+ 150,
+ 151,
+ 152,
+ 153,
+ 153,
+ 154,
+ 155,
+ 155,
+ 156,
+ 157,
+ 158,
+ 158,
+ 159,
+ 160,
+ 160,
+ 161,
+ 162,
+ 163,
+ 163,
+ 164,
+ 165,
+ 165,
+ 166,
+ 167,
+ 168,
+ 168,
+ 169,
+ 170,
+ 170,
+ 171,
+ 172,
+ 173,
+ 173,
+ 174
+ ]
+ }
+ ],
+ "copy": [
+ {
+ "text": "A path of your own.",
+ "first": 0,
+ "last": 242
+ },
+ {
+ "text": "Input",
+ "first": 0,
+ "last": 242
+ },
+ {
+ "text": "Camera path",
+ "first": 0,
+ "last": 242
+ },
+ {
+ "text": "Make room. Move around.",
+ "first": 0,
+ "last": 109
+ },
+ {
+ "text": "Change direction.",
+ "first": 110,
+ "last": 191
+ },
+ {
+ "text": "Let it unfold.",
+ "first": 192,
+ "last": 242
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 32,
+ 110,
+ 121,
+ 144,
+ 192,
+ 214,
+ 242
+ ],
+ "requested_phases": [
+ [
+ 0,
+ 32,
+ "Widen for the red wheel"
+ ],
+ [
+ 32,
+ 110,
+ "Orbit -35 degrees"
+ ],
+ [
+ 110,
+ 144,
+ "Truck right"
+ ],
+ [
+ 144,
+ 192,
+ "Counter-orbit +10 degrees"
+ ],
+ [
+ 192,
+ 214,
+ "Observe; camera rests"
+ ],
+ [
+ 214,
+ 242,
+ "Retreat"
+ ]
+ ],
+ "reference_explainer": "../teaser_meridian_compound_motor_dust_explained_v2.mp4",
+ "camera_visualization": "teaser_v7/camera_path.json",
+ "synchronization": "Raw output, retained selected model-input video and requested camera pose use the same output index 0\u2013242. Prepared-input indices follow recorded tmap 0\u2013174; repetitions are intentional.",
+ "request_record": "../longtake_edit/multisegment/motor_dust_sixphase_opposed35_wheelmargin_live243_seed3407/path_design.json"
+ },
+ {
+ "key": "powder",
+ "title": "Move around. Move closer.",
+ "start": 721,
+ "frames": 175,
+ "seconds": 7.291666666666667,
+ "segment": "teaser_v7/powder.mp4",
+ "inputs": [
+ {
+ "key": "powder",
+ "file": "../meridian_grand_l150_powder_orbit45_push85_175/out.mp4",
+ "sha256": "361ee081f0948b09bbb20ba60c151a8164481d7ab33e88e2c971b8dffd21d8a0",
+ "output_rect": [
+ 186,
+ 134,
+ 1548,
+ 878
+ ],
+ "first_frame": 0,
+ "last_frame": 174,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 125,
+ 126,
+ 127,
+ 128,
+ 129,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ 140,
+ 141,
+ 142,
+ 143,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 151,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 157,
+ 158,
+ 159,
+ 160,
+ 161,
+ 162,
+ 163,
+ 164,
+ 165,
+ 166,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 174
+ ]
+ }
+ ],
+ "copy": [
+ {
+ "text": "Move around. Move closer.",
+ "first": 0,
+ "last": 174
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 87,
+ 174
+ ]
+ },
+ {
+ "key": "ballet",
+ "title": "A still image, another view.",
+ "start": 896,
+ "frames": 124,
+ "seconds": 5.166666666666667,
+ "segment": "teaser_v7/ballet.mp4",
+ "inputs": [
+ {
+ "key": "ballet",
+ "file": "../meridian_ballet_l150_male_clean60/out.mp4",
+ "sha256": "07e5e5cab0050cfebb326fcf16179c907097418716253520d68204934011514c",
+ "output_rect": [
+ 592,
+ 214,
+ 1264,
+ 716
+ ],
+ "first_frame": 0,
+ "last_frame": 123,
+ "output_start_frame": 0,
+ "still": false,
+ "prepared_input_frames": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "key": "input",
+ "file": "../overnight/sources/dutch_ballet_male_1900.png",
+ "sha256": "214085bb2bda88513af97eca9b0535dde0a2f8592014d4163efb5d7609e07ced",
+ "still": true,
+ "first_frame": 0,
+ "last_frame": 0,
+ "output_start_frame": 0,
+ "output_rect": [
+ 64,
+ 438,
+ 480,
+ 270
+ ]
+ }
+ ],
+ "copy": [
+ {
+ "text": "A still image, another view.",
+ "first": 0,
+ "last": 123
+ },
+ {
+ "text": "One image.",
+ "first": 0,
+ "last": 123
+ },
+ {
+ "text": "Another view.",
+ "first": 0,
+ "last": 123
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 1,
+ 23,
+ 24,
+ 25,
+ 48,
+ 62,
+ 123
+ ]
+ },
+ {
+ "key": "painting",
+ "title": "Beyond the frame.",
+ "start": 1020,
+ "frames": 73,
+ "seconds": 3.0416666666666665,
+ "segment": "teaser_v7/painting.mp4",
+ "inputs": [
+ {
+ "key": "painting",
+ "file": "preview_assets/napoleon.mp4",
+ "sha256": "c0d0cdd43fdcbce112d47c16bef032e54f2441c8e57305fff6bf6f0b128a0b5e",
+ "output_rect": [
+ 640,
+ 134,
+ 640,
+ 878
+ ],
+ "first_frame": 0,
+ "last_frame": 72,
+ "output_start_frame": 0,
+ "still": false
+ }
+ ],
+ "copy": [
+ {
+ "text": "Beyond the frame.",
+ "first": 0,
+ "last": 72
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 36,
+ 72
+ ],
+ "provenance": "User identifies this as a video generated from a painting. Exact input reproduction, recipe, camera path and public promotional clearance not supplied."
+ },
+ {
+ "key": "outro",
+ "title": "One event. Any time. Anywhere.",
+ "start": 1093,
+ "frames": 60,
+ "seconds": 2.5,
+ "segment": "teaser_v7/outro.mp4",
+ "inputs": [],
+ "copy": [
+ {
+ "text": "MERIDIAN",
+ "first": 0,
+ "last": 59
+ },
+ {
+ "text": "One event. Any time. Anywhere.",
+ "first": 0,
+ "last": 59
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "sample_frames": [
+ 0,
+ 30,
+ 59
+ ]
+ }
+ ],
+ "full_decode": true,
+ "exact_pts": true,
+ "decoded_concat_identity": true,
+ "audio": false,
+ "new_inference": false,
+ "composition_samples_viewed": true,
+ "continuous_visual_review": false,
+ "edit": "v6 picture edit retained. NBA: One moment. then warm-gold bold Revisited. after input time freezes. Robot: One event. then warm-gold bold Many perspectives. after a short pause. Fixed baselines and six-frame emphasis fades, no movement or typewriter effects. Napoleon: Beyond the frame. Final brand card unchanged. Complete native-24-fps sources, fit-down only; no crop, upscaling, generated-shot dissolve, interpolation, output retime or new inference. Silent CRF15 H264. Page and v3/v4/v5/v6 preserved.",
+ "selection": "One moment \u2192 revisit it; one event \u2192 multiple perspectives; authored camera travel with input/path context \u2192 airborne action \u2192 a still photograph \u2192 Beyond the frame.",
+ "omitted": {
+ "moto90": "Repeated motorcycle subject and visibly clipped late front wheel.",
+ "jellyfish": "Removed to keep the event-to-camera-to-image progression compact.",
+ "bed_arc": "Top-right generated view replaced with the actual shared model input, as requested.",
+ "ambassadors": "Original Napoleon painting example restored, as requested."
+ },
+ "caveats": [
+ "Camera labels describe authored controls, not measured recovered camera motion.",
+ "Robot generated views share input timing but are independently generated; fine cloth and hand details may disagree.",
+ "Motorcycles retain soft spokes and inferred distant terrain; source/output pose and dust can disagree.",
+ "Powder has inferred far-background details and tilted wall/ground; the clip does not show a complete landing.",
+ "Ballet and painting reveal inferred details. Ballet has one fixed comparison layout; its former 24-frame introduction is removed.",
+ "Camera diagram uses recorded requested poses, not measured output motion. Its fixed oblique projection preserves relative geometry; glyph size is illustrative, not calibrated field of view.",
+ "Napoleon input painting, generation recipe and camera records are unavailable; no original-input comparison is fabricated."
+ ],
+ "rights": "Local research only; public promotional clearance remains unverified. See TEASER_V7_NOTES.md.",
+ "visual_review": {
+ "reviewed_utc": "2026-09-13T19:51:18.765150+00:00",
+ "sheets": [
+ "teaser_v7/title_reveals.jpg",
+ "teaser_v7/story_transitions.jpg",
+ "teaser_v7/composition_overview.jpg"
+ ],
+ "individual_frames": [
+ "teaser_v7/nba_065.jpg",
+ "teaser_v7/bed_020.jpg",
+ "teaser_v7/painting_036.jpg"
+ ],
+ "scope": "Both title reveals at four representative frames; four distributed frames per chapter; two frames on each side of all chapter cuts; three individual updated-title frames. Static inspection only.",
+ "notes": "Prefixes remain fixed while warm-gold bold suffixes appear; no title overlap or baseline jump seen in samples. Napoleon reads Beyond the frame. Final brand card retained.",
+ "continuous_playback": false
+ },
+ "reused_v6_assets": {
+ "opening.png": "aef3b72f137260240554afba02f88361b3863876ce753777ec61066d53d6e7a6",
+ "camera_path.mp4": "4035a1288568cc7560e5eac40db1cbfec83ef049a2fcd68d9c2f10a6ac467831"
+ }
+}
diff --git a/videos-all/longtake_showcase/teaser_v7/validation.json b/videos-all/longtake_showcase/teaser_v7/validation.json
new file mode 100644
index 0000000000000000000000000000000000000000..c63206bef73c475f7b56e6e487765a5bbfdeba35
--- /dev/null
+++ b/videos-all/longtake_showcase/teaser_v7/validation.json
@@ -0,0 +1,180 @@
+{
+ "tested_utc": "2026-09-13T19:50:37.578545+00:00",
+ "full_decode": true,
+ "exact_pts": true,
+ "decoded_concat_identity": true,
+ "source_hashes": true,
+ "source_frame_alignment": [
+ {
+ "key": "nba",
+ "source": "nba",
+ "compared_frames": 243,
+ "output_offset": 0,
+ "max_source_luma_mse": 3.1628472805023193,
+ "mean_source_luma_mse": 1.9834433516847745
+ },
+ {
+ "key": "bed",
+ "source": "bed_main",
+ "compared_frames": 175,
+ "output_offset": 0,
+ "max_source_luma_mse": 1.1093363761901855,
+ "mean_source_luma_mse": 0.8837321994985853
+ },
+ {
+ "key": "bed",
+ "source": "bed_input",
+ "compared_frames": 175,
+ "output_offset": 0,
+ "max_source_luma_mse": 2.6741244792938232,
+ "mean_source_luma_mse": 1.7808419578416006
+ },
+ {
+ "key": "bed",
+ "source": "bed_cross",
+ "compared_frames": 175,
+ "output_offset": 0,
+ "max_source_luma_mse": 3.139417886734009,
+ "mean_source_luma_mse": 2.196172341278621
+ },
+ {
+ "key": "bed",
+ "source": "bed_reverse",
+ "compared_frames": 175,
+ "output_offset": 0,
+ "max_source_luma_mse": 3.007281541824341,
+ "mean_source_luma_mse": 2.2241779020854406
+ },
+ {
+ "key": "motor",
+ "source": "motor",
+ "compared_frames": 243,
+ "output_offset": 0,
+ "max_source_luma_mse": 2.2255780696868896,
+ "mean_source_luma_mse": 1.4992641867924128
+ },
+ {
+ "key": "motor",
+ "source": "motor_input",
+ "compared_frames": 243,
+ "output_offset": 0,
+ "max_source_luma_mse": 3.443112373352051,
+ "mean_source_luma_mse": 1.3660355867672358
+ },
+ {
+ "key": "motor",
+ "source": "camera_path",
+ "compared_frames": 243,
+ "output_offset": 0,
+ "max_source_luma_mse": 0.2456374615430832,
+ "mean_source_luma_mse": 0.13008754101003148
+ },
+ {
+ "key": "powder",
+ "source": "powder",
+ "compared_frames": 175,
+ "output_offset": 0,
+ "max_source_luma_mse": 0.7815242409706116,
+ "mean_source_luma_mse": 0.6495901920114244
+ },
+ {
+ "key": "ballet",
+ "source": "ballet",
+ "compared_frames": 124,
+ "output_offset": 0,
+ "max_source_luma_mse": 0.3185981810092926,
+ "mean_source_luma_mse": 0.22866104513166413,
+ "input_image_compared_frames": 124,
+ "max_input_luma_mse": 0.10184413939714432
+ },
+ {
+ "key": "painting",
+ "source": "painting",
+ "compared_frames": 73,
+ "output_offset": 0,
+ "max_source_luma_mse": 2.0551910400390625,
+ "mean_source_luma_mse": 1.4782481062902164
+ }
+ ],
+ "robot_top_right_actual_input": true,
+ "robot_all_four_regions_frame_aligned": true,
+ "original_napoleon_restored": true,
+ "robot_input_label_removed": true,
+ "ballet_fixed_layout_from_first_frame": true,
+ "opening_wordmark_preserved_and_subtitle_fades": true,
+ "motorcycle_input_and_recorded_pose_synchronized": true,
+ "camera_projection_and_glyph_geometry_verified": true,
+ "two_beat_title_checks": [
+ {
+ "key": "nba",
+ "fade_start": 59,
+ "fade_end": 65,
+ "checked_frames": 243,
+ "max_prefix_mse": 1.5745065212249756,
+ "fully_visible_color_rgb": [
+ 193.0,
+ 179.0,
+ 141.0
+ ],
+ "fade_levels": [
+ 0.0,
+ 4.358339309692383,
+ 8.811671257019043,
+ 13.05240535736084,
+ 17.469409942626953,
+ 21.69955825805664,
+ 26.046606063842773
+ ]
+ },
+ {
+ "key": "bed",
+ "fade_start": 14,
+ "fade_end": 20,
+ "checked_frames": 175,
+ "max_prefix_mse": 1.444284439086914,
+ "fully_visible_color_rgb": [
+ 194.0,
+ 178.0,
+ 140.0
+ ],
+ "fade_levels": [
+ 0.0,
+ 4.345119953155518,
+ 8.58596420288086,
+ 12.99185562133789,
+ 17.253103256225586,
+ 21.585458755493164,
+ 25.769392013549805
+ ]
+ }
+ ],
+ "unchanged_v6_segments_byte_identical": {
+ "intro": true,
+ "motor": true,
+ "powder": true,
+ "ballet": true,
+ "outro": true
+ },
+ "painting_caption": "Beyond the frame.",
+ "preserved_files": 471,
+ "preserved_hashes": true,
+ "continuous_visual_review": false,
+ "comparison": "Every moving region against its indexed raw source, and every still-image region against its input; Lanczos fit-down and CRF15 error allowed below luma MSE 10.",
+ "composition_samples_viewed": true,
+ "visual_review": {
+ "reviewed_utc": "2026-09-13T19:51:18.765150+00:00",
+ "sheets": [
+ "teaser_v7/title_reveals.jpg",
+ "teaser_v7/story_transitions.jpg",
+ "teaser_v7/composition_overview.jpg"
+ ],
+ "individual_frames": [
+ "teaser_v7/nba_065.jpg",
+ "teaser_v7/bed_020.jpg",
+ "teaser_v7/painting_036.jpg"
+ ],
+ "scope": "Both title reveals at four representative frames; four distributed frames per chapter; two frames on each side of all chapter cuts; three individual updated-title frames. Static inspection only.",
+ "notes": "Prefixes remain fixed while warm-gold bold suffixes appear; no title overlap or baseline jump seen in samples. Napoleon reads Beyond the frame. Final brand card retained.",
+ "continuous_playback": false
+ }
+}
diff --git a/videos-all/meridian_ballet_l150_female_reverse45.mp4 b/videos-all/meridian_ballet_l150_female_reverse45.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..2621c734f9421bea9692ab65a1dd6b90dbb7df7f
--- /dev/null
+++ b/videos-all/meridian_ballet_l150_female_reverse45.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f4d0709082e46d607f06bafb201e5cef2c69325fd7c234d2d23d8154bd4c21b8
+size 1263368
diff --git a/videos-all/meridian_ballet_l150_female_reverse45/out.mp4 b/videos-all/meridian_ballet_l150_female_reverse45/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..0a566e428074b50029dc4b5601ea8f92e07eaa94
--- /dev/null
+++ b/videos-all/meridian_ballet_l150_female_reverse45/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f0a63830afe0e926f82b8f50fa2c7647b61c9a5c200df6a73de86624449b2c79
+size 733368
diff --git a/videos-all/meridian_ballet_t30_female_arc/out.mp4 b/videos-all/meridian_ballet_t30_female_arc/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..aa240b3b5403fff098716040725178294522360d
--- /dev/null
+++ b/videos-all/meridian_ballet_t30_female_arc/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:42d5b7ffc39418474cdd845dcfc8e4d5e65f6a892b88dd077596d21c24e1f3e8
+size 458631
diff --git a/videos-all/meridian_ballet_t30_male_lowarc/out.mp4 b/videos-all/meridian_ballet_t30_male_lowarc/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..e8f1f16ebc1870c0178e2096f3ce07a7af1a2dde
--- /dev/null
+++ b/videos-all/meridian_ballet_t30_male_lowarc/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fc70f089a626404a3720943f6d720fd9bfe34f8dd5d071717e25665a66948fe8
+size 382999
diff --git a/videos-all/meridian_longtake_l150_nba3_apex_right14_175/out.mp4 b/videos-all/meridian_longtake_l150_nba3_apex_right14_175/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..0a608693dfc339d590b031c8e57484989fea4da1
--- /dev/null
+++ b/videos-all/meridian_longtake_l150_nba3_apex_right14_175/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:49d33d29dca587f252dc43171e6b98513348770332ca44a8eb3a8b46b4300fb0
+size 5943480
diff --git a/videos-all/meridian_longtake_l150_nba3_apex_right14_175/render.mp4 b/videos-all/meridian_longtake_l150_nba3_apex_right14_175/render.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..6f1f78ab7a9b3217ebdcd4c95c8fd202f39bb4da
--- /dev/null
+++ b/videos-all/meridian_longtake_l150_nba3_apex_right14_175/render.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e4f130524c2e09351203ca6dd410b3505031e72cdb4411e3d231787dba62bd23
+size 2151178
diff --git a/videos-all/meridian_longtake_l150_nba3_apex_right14_175/source.mp4 b/videos-all/meridian_longtake_l150_nba3_apex_right14_175/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..4ea6a05d8c498462535f0aeeb048f09ef2b4d9a8
--- /dev/null
+++ b/videos-all/meridian_longtake_l150_nba3_apex_right14_175/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:642f992fdc516c57fbaeabd9c4a6aa773c76fb9f1fd342412e20baa27b3dbb46
+size 4198049
diff --git a/videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4 b/videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..0de1f05eea74449526d137c6f9d0e8987e78c862
--- /dev/null
+++ b/videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4285c59b5c964b83c5ba782950ae3f930f6dd213b85dea9837bdbdcf94174b09
+size 973798
diff --git a/videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4 b/videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..c81af2eb0e80ef6c81ad0f78dba57a696808eb80
--- /dev/null
+++ b/videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0db2bcf81426da121b987994c85aea5ce6c616b447d98daf89b49e24758454c5
+size 1140371
diff --git a/videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4 b/videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..a5c8a02e0b8620de590e70b42e77a9f4b51e93d9
--- /dev/null
+++ b/videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fa15153f8b204005aa0a92b06ab17cab7ae373584394ad706bcf3f7b8a3ac99e
+size 3863134
diff --git a/videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4 b/videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..7cb11e97948c79bfd5978de282957f5c72803fdb
--- /dev/null
+++ b/videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:57ba804b4b0cec7dfe361931a95bbfed5fef6511e053fb96635198fb77107829
+size 2255870
diff --git a/videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4 b/videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..5cfd55eb7d49e43e47a8bcec5558e8e0c377b046
--- /dev/null
+++ b/videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:76356a28f687516e3470d5e915c82eb38b9841ae88a2951ecaf9aac95179aac8
+size 1677846
diff --git a/videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4 b/videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..88e58423f5eaca6c1415f3f2f350c9a8a79be6ee
--- /dev/null
+++ b/videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e05e9b8d7927c5f0ee935c1426d779fe91cd0881a40f0568795074ad163b93b7
+size 1184125
diff --git a/videos-all/meridian_material_l150_charge_event_return22/out.mp4 b/videos-all/meridian_material_l150_charge_event_return22/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..97c49253ec58c284a7b828f8296da684f0d5f3c8
--- /dev/null
+++ b/videos-all/meridian_material_l150_charge_event_return22/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0efd7b01b650bddaa6f3476a22d7c830f2b54bb3e807e30c717e144e2ffebb7d
+size 1604604
diff --git a/videos-all/meridian_material_l150_charge_event_return22/source.mp4 b/videos-all/meridian_material_l150_charge_event_return22/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..4513a8f10cb94fe623292a7bcad715ee8199dba6
--- /dev/null
+++ b/videos-all/meridian_material_l150_charge_event_return22/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:42cc7f068d27624227070719d32e66bb9a96f74d5483b25c0d8cdd6d0c26182f
+size 776665
diff --git a/videos-all/meridian_motion_l150_moto_event_return30/out.mp4 b/videos-all/meridian_motion_l150_moto_event_return30/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..c776e3902ba95a6dfed8b7458b831f44d47f4073
--- /dev/null
+++ b/videos-all/meridian_motion_l150_moto_event_return30/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c1b466a1182547c66776e24220c4be16f673cf99f1d0486c6dee359fefab1870
+size 3457246
diff --git a/videos-all/meridian_motion_l150_moto_event_return30/source.mp4 b/videos-all/meridian_motion_l150_moto_event_return30/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..5fca24f4dc95c6863c2159bb406149822ffb38cb
--- /dev/null
+++ b/videos-all/meridian_motion_l150_moto_event_return30/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4627087a4251d37b262f9abcfb6b00c8cbc71b2c0224aef8763fe108b849f8d0
+size 1315555
diff --git a/videos-all/meridian_nba3_l150_air_left14/out.mp4 b/videos-all/meridian_nba3_l150_air_left14/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..aad887dbf1af6a298ec9a9c97eee5163b4a7e297
--- /dev/null
+++ b/videos-all/meridian_nba3_l150_air_left14/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ab51eaf579ca34aba20ab110db79cd5bd9381505b653a6a380837378c9105662
+size 2554018
diff --git a/videos-all/meridian_nba3_l150_air_right14/out.mp4 b/videos-all/meridian_nba3_l150_air_right14/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..451f501477cc2f126cc4e5392d17090c2bb1cd9a
--- /dev/null
+++ b/videos-all/meridian_nba3_l150_air_right14/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:998230f1881ee760b55c8f09899c4488700655ca54fa7115fdd2bf5910842dc5
+size 2519607
diff --git a/videos-all/meridian_nba3_l150_moment38_left14/out.mp4 b/videos-all/meridian_nba3_l150_moment38_left14/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..a925cddd68aeeddf7bb5aff730b356c3ddcb66aa
--- /dev/null
+++ b/videos-all/meridian_nba3_l150_moment38_left14/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dd3ae581a8a3ed5b9d078765deb74c65eba3050a0029609608ba838806996079
+size 2531191
diff --git a/videos-all/meridian_nba3_l150_moment54_right14/out.mp4 b/videos-all/meridian_nba3_l150_moment54_right14/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..f8b4453b59eed1a9993ad0b138f99b1fb6ea47dc
--- /dev/null
+++ b/videos-all/meridian_nba3_l150_moment54_right14/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bcabd1bcf2204bcdb1df51c267c3f15b3eef7a9c9d6130d5eeff259d42ec7b5b
+size 2551579
diff --git a/videos-all/meridian_return_l150_berry_event22/out.mp4 b/videos-all/meridian_return_l150_berry_event22/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..f8e99dc15ff40a3dd1e002c5f7a5c2abc8d34280
--- /dev/null
+++ b/videos-all/meridian_return_l150_berry_event22/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:08fbb622a5cfe7ba17ca85d523c626b6e6298e742e24b6282e3b799d33dc0224
+size 2283256
diff --git a/videos-all/meridian_return_l150_berry_event22/source.mp4 b/videos-all/meridian_return_l150_berry_event22/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..0ba3398f2f8a2dc07f32ad987f0b3dc4a2e8d034
--- /dev/null
+++ b/videos-all/meridian_return_l150_berry_event22/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f98f1bd225bfe4baf14eaf90b7ea7243d828f23dfad82307f9d643fbb1b2db32
+size 1217375
diff --git a/videos-all/nba3_lora_editorial/README.md b/videos-all/nba3_lora_editorial/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5ceb3157fddd28148e5480ee83303d82fbdd165e
--- /dev/null
+++ b/videos-all/nba3_lora_editorial/README.md
@@ -0,0 +1,17 @@
+# NBA3 / LoRA150 editorial references
+
+**New film: [One event. Three instants. / 15.54 s](../teaser_meridian_nba3_lora_edit_v2.mp4)** · [Four matched comparisons](preview.html)
+
+Source action → generated held early flight → source action → generated ball sweep → two generated viewpoints at the same high point → the **source footage** completes the dunk. Source segments are explicitly labeled, not presented as generated action. Input thumbnails, original-file clocks and recorded camera paths remain visible.
+
+The film keeps the teacher cut's timing/layout and selects contiguous LoRA output frames **24–95** for each generated insert. No generated-output retiming, spatial output crop, interpolation or repair. [Exact specification](../teacher_followups/film_spec_nba3_lora_edit_v2.json), [edit manifest](../teacher_followups/film_edit_nba3_lora_edit_v2.json), [film validation](review/film_v2_validation.json).
+
+All four pairs passed exact camera-array checks (maximum difference **0.0**), identical model-input MP4 bytes, original-source clock mapping and full 24-fps input/output/warp decoding. Warp MP4 bytes differ; these are **two sampling recipes, not an isolated LoRA ablation**. All four browser cases passed frame stepping, hold clocks and playback checks. See `validation.json` and `browser_validation.json`.
+
+Visual coverage: all four LoRA takes at 32 distributed frames; matched native frame62 in both recipes; native input62 for the three unique moments; all eight film compositions and sixteen cut-boundary samples. Faces, hands, crowd, signage and hidden hoop structure remain imperfect. This supports an editorial candidate, not pristine reconstruction or continuous-motion certification. [Shot decisions](selection.json).
+
+Local silent research draft. Source-use/publication rights are not established; previous films and full raw outputs are preserved.
+
+Four same-control LoRA150 reruns of the selected teacher shots in `../teaser_meridian_teacher_nba3_edit_v1.mp4`: moment 38 left, moment 54 right, and moment 70 left/right. Only previously source-qualified held instants; no rim-contact repair claim. Original full-event plate, not the new subject crop.
+
+Recipe: full-000200 + lora-000150, CLI 4 steps, shift 3, seed 1234. Teacher reference: no LoRA, CLI 30 steps, shift 12, seed 1234. Compare actual recorded arrays and decoded inputs before calling them matched. No global default change or automatic promotion. Raw teacher film is preserved.
diff --git a/videos-all/nba3_teacher30/nba3_full_event.mp4 b/videos-all/nba3_teacher30/nba3_full_event.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..e5775d60c5c199192514d6d5c387b07d3ec3c247
--- /dev/null
+++ b/videos-all/nba3_teacher30/nba3_full_event.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5d055116a5081a6a8d07dbd1f285fe99d1591e040dd9d27faee65af548085313
+size 12199062
diff --git a/videos-all/overnight/sources/dutch_ballet_female_2575.png b/videos-all/overnight/sources/dutch_ballet_female_2575.png
new file mode 100644
index 0000000000000000000000000000000000000000..389e5ab9de03a35fa83f7018adbaeb5e208395e1
--- /dev/null
+++ b/videos-all/overnight/sources/dutch_ballet_female_2575.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e3a7b9ca86655cba6536d46b95b99ebbd29d1ab7108d23d6e442588df013bf65
+size 279566
diff --git a/videos-all/overnight/sources/dutch_ballet_male_1900.png b/videos-all/overnight/sources/dutch_ballet_male_1900.png
new file mode 100644
index 0000000000000000000000000000000000000000..1759812db9b505f33052315b213e0f5df5027b18
--- /dev/null
+++ b/videos-all/overnight/sources/dutch_ballet_male_1900.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:214085bb2bda88513af97eca9b0535dde0a2f8592014d4163efb5d7609e07ced
+size 384369
diff --git a/videos-all/research_examples_v1/README.md b/videos-all/research_examples_v1/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f54fb5b2dc8316dbc51e6ea591ca01dee27d3d4b
--- /dev/null
+++ b/videos-all/research_examples_v1/README.md
@@ -0,0 +1,75 @@
+# Research-page examples
+
+Input-inset derivatives for [the concise research page](../../docs/research.html).
+These are edits of existing results, not new inference runs. Original media is unchanged.
+
+**Selection update:** the current pages replace the main motocross and female-ballet videos and
+omit the supplementary motocross hold. See the [current selection notes](../research_examples_v2/README.md).
+The tables, build script, manifest, and validation below document the original v1 exports and ordering.
+
+## Selection
+
+Frame intervals below are zero-based and inclusive. All exports are silent, 24 fps,
+1920 × 1088 H.264. Fit/padding preserves the full source and generated frame; the inset
+covers a corner of the generated view. There is no output cropping, repair, interpolation,
+or additional retiming. The move-film sports inputs were already slowed before generation.
+
+| Page example | Generated take / selected frames | Aligned input | Unoverlaid output |
+| --- | --- | --- | --- |
+| [Strawberries](berry.mp4) | `meridian_return_l150_berry_event22`, 0–123 | [Video](../meridian_return_l150_berry_event22/source.mp4) | [Output](../meridian_return_l150_berry_event22/out.mp4) |
+| [Motocross](moto.mp4) | `meridian_longtake_t30_moto_dust_retreat25`, 0–174 | [Video](../meridian_longtake_t30_moto_dust_retreat25/source.mp4) | [Output](../meridian_longtake_t30_moto_dust_retreat25/out.mp4) |
+| [Female ballet](ballet.mp4) | `meridian_ballet_t30_female_arc`, 24–119 | [Actual still image](../overnight/sources/dutch_ballet_female_2575.png) | [Full output](../meridian_ballet_t30_female_arc/out.mp4) |
+| [Robot folding cloth](robot.mp4) | `va_pi3_hi`, 0–123 | [Video](../va_pi3_hi/source.mp4) | [Output](../va_pi3_hi/out.mp4) |
+| [Motocross hold](moto_return.mp4) | `meridian_motion_l150_moto_event_return30`, 0–123 | [Video](../meridian_motion_l150_moto_event_return30/source.mp4) | [Output](../meridian_motion_l150_moto_event_return30/out.mp4) |
+| [Charge animation](charge.mp4) | `meridian_material_l150_charge_event_return22`, 0–123 | [Video](../meridian_material_l150_charge_event_return22/source.mp4) | [Output](../meridian_material_l150_charge_event_return22/out.mp4) |
+| [Male ballet](ballet_male.mp4) | `meridian_ballet_t30_male_lowarc`, 24–119 | [Actual still image](../overnight/sources/dutch_ballet_male_1900.png) | [Full output](../meridian_ballet_t30_male_lowarc/out.mp4) |
+| [Gymnastics](gymnast.mp4) | `meridian_longtake_t30_gymnast_pink_rise12`, 0–174 | [Video](../meridian_longtake_t30_gymnast_pink_rise12/source.mp4) | [Output](../meridian_longtake_t30_gymnast_pink_rise12/out.mp4) |
+| [Snow sports](powder.mp4) | `meridian_longtake_t30_powder_frontal_rise18`, 0–174 | [Video](../meridian_longtake_t30_powder_frontal_rise18/source.mp4) | [Output](../meridian_longtake_t30_powder_frontal_rise18/out.mp4) |
+
+Video insets use the same frame indices as the generated output, taken from each run's
+time-mapped `source.mp4`. They hold when source time holds; they are not independent
+background playback. Ballet insets are the actual PNG inputs, not a moving dance clip.
+The two dancers are separate images, not two moments of one jump.
+
+## NBA edit: source footage and generated views
+
+[NBA example](nba.mp4) preserves the seven non-brand segments and hard cuts of the
+approved [NBA v2 edit](../teacher_followups/film_edit_nba3_lora_edit_v2.json).
+Only its 36-frame ending brand card is omitted: 337 frames, 14.042 seconds remain.
+This is **an editorial sequence, not one continuous model generation**.
+
+| Film frames | Content | Retained input/output frames |
+| --- | --- | --- |
+| 0–37 | Original action, explicitly labeled **SOURCE FOOTAGE / NOT GENERATED** | [Source plate](../nba3_teacher30/nba3_full_event.mp4), 0–37 |
+| 38–109 | Generated view at the first held moment | [Left view](../meridian_nba3_l150_moment38_left14/out.mp4), 24–95 |
+| 110–124 | Original action | Source plate, 39–53 |
+| 125–196 | Generated view at the second held moment | [Right view](../meridian_nba3_l150_moment54_right14/out.mp4), 24–95 |
+| 197–211 | Original action | Source plate, 55–69 |
+| 212–283 | Two generated views of the same held instant | [View A](../meridian_nba3_l150_air_left14/out.mp4), [View B](../meridian_nba3_l150_air_right14/out.mp4), both 24–95 |
+| 284–336 | Original dunk completion and landing | Source plate, 71–123 |
+
+Generated segments include the matching input inset. Original segments have no
+redundant inset. In particular, the completed dunk and landing are **not generated**.
+The research method figure uses a [different, explicitly linked NBA take](../meridian_longtake_l150_nba3_apex_right14_175/out.mp4).
+
+## Credits and limitations
+
+- Strawberries: Mixkit clip 101338. See the retained license and [return-film notes](../return_showcase/README.md).
+- Motocross, gymnastics, snow sports: Mystery Box LLC (2014), Jacob + Katie Schwarz. Local research use; public promotional clearance is not established. The original move-film review page, `videos-all/longtake_edit/move.html`, is local-only and not part of the Hub snapshot.
+- Charge: © 2022 Blender Foundation, CC BY 4.0; this is an animated source, not captured live action. See [return-film notes](../return_showcase/README.md).
+- Ballet: Altin Kaftira / ArtAlt, Dutch ballet footage, frames 2575 and 1900 used as still inputs. Public reuse is unverified. See [ballet v1 notes](../teacher_followups/README.md).
+- NBA: user-provided footage; public-use clearance remains pending. See [NBA editorial notes](../nba3_lora_editorial/README.md).
+- Robot: Physical Intelligence folding-cloth reel, retained plate `pi_w3.mp4`; selected from the local-only experimental gallery (`DEMOS.html`), with provenance recorded in [the candidate list](../candidates.md). Public-use clearance remains pending. Text already present in the source is not a Meridian performance claim.
+
+Unseen regions remain generated. The approved ballet views contain stage/floor
+completion artifacts; the other examples are not claims of perfect geometry or motion.
+The older experimental gallery is a visual reference, not current CLI documentation.
+
+## Reproduction and checks
+
+`build.py` records the layout and selection; it refuses to overwrite existing media.
+For a clean rebuild, run it from the release root with the documented Python environment.
+The [manifest](manifest.json) retains exact FFmpeg commands, frame intervals, original
+input hashes, and the page's main/collapsed ordering. [Validation](validation.json)
+records decode, timing, inset-alignment, and static page checks. Sampled frame inspection
+does not replace a continuous human motion review or browser playback test.
diff --git a/videos-all/research_examples_v1/ballet.jpg b/videos-all/research_examples_v1/ballet.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..97720255cba775274920aaeb9dfeff9a302489cf
Binary files /dev/null and b/videos-all/research_examples_v1/ballet.jpg differ
diff --git a/videos-all/research_examples_v1/ballet.mp4 b/videos-all/research_examples_v1/ballet.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..38eeed60ae9be535b15462e8ec44eb417c7b790f
--- /dev/null
+++ b/videos-all/research_examples_v1/ballet.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8c3ebafb7e30871e1aaab14d060d9445bd3736f551ef6424ced1dc5538fda981
+size 573673
diff --git a/videos-all/research_examples_v1/ballet_male.jpg b/videos-all/research_examples_v1/ballet_male.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..1fb0504a2fb7adc17bcf8567140eab99d8793ea1
Binary files /dev/null and b/videos-all/research_examples_v1/ballet_male.jpg differ
diff --git a/videos-all/research_examples_v1/ballet_male.mp4 b/videos-all/research_examples_v1/ballet_male.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..fe42a93162909ba91700b4c1440efee167817b79
--- /dev/null
+++ b/videos-all/research_examples_v1/ballet_male.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ea2dfa2ccdd5a08fc87670cd3b818c8ef599ee9d8a04eaefcc4ee944cea4f7d
+size 514740
diff --git a/videos-all/research_examples_v1/berry.jpg b/videos-all/research_examples_v1/berry.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ff52bff81f8f9158647ac3f4134300222433ccf6
--- /dev/null
+++ b/videos-all/research_examples_v1/berry.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8e5700d87210029e0fb84a7251231b5d651bb95b7a92b043b6cbd0d48d6d5840
+size 156645
diff --git a/videos-all/research_examples_v1/berry.mp4 b/videos-all/research_examples_v1/berry.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..cb7c770d9bf132776ae83dd2449c4ff32730865e
--- /dev/null
+++ b/videos-all/research_examples_v1/berry.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2a4575cfbeeaa23d39c983f3a32b6fd7197f5cfab7688a35bb958127e41d87f1
+size 4134891
diff --git a/videos-all/research_examples_v1/charge.jpg b/videos-all/research_examples_v1/charge.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..3d93c2170fb652cb5917cfcc30c6b5e0f649f730
--- /dev/null
+++ b/videos-all/research_examples_v1/charge.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:895b6729a23829d1ef983a9b42eb57eb6638e04a226f83e335d75ac5dfc5197c
+size 125379
diff --git a/videos-all/research_examples_v1/charge.mp4 b/videos-all/research_examples_v1/charge.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..2a9a58a022f5bb10c9194689ab55961716b753d8
--- /dev/null
+++ b/videos-all/research_examples_v1/charge.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:be4f31cb921075be99ec7c0c803e3c660f61109ea801a14cc75d596d495b8729
+size 2780173
diff --git a/videos-all/research_examples_v1/gymnast.jpg b/videos-all/research_examples_v1/gymnast.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..5aaf80c3d195dd8dbcbcbc459c9354265b63435a
Binary files /dev/null and b/videos-all/research_examples_v1/gymnast.jpg differ
diff --git a/videos-all/research_examples_v1/gymnast.mp4 b/videos-all/research_examples_v1/gymnast.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..6099c90af49c341f83dc6f5f5849039ed953cbb0
--- /dev/null
+++ b/videos-all/research_examples_v1/gymnast.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1aaacea862793d9d4dbe4f5ace9f38c0486b31a93490ddb49c26a9256952367b
+size 1818758
diff --git a/videos-all/research_examples_v1/manifest.json b/videos-all/research_examples_v1/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..88d1b01dedb28d59904a21625b0478ad078a24d9
--- /dev/null
+++ b/videos-all/research_examples_v1/manifest.json
@@ -0,0 +1,1220 @@
+{
+ "fps": 24,
+ "width": 1920,
+ "height": 1088,
+ "main": [
+ "nba",
+ "berry",
+ "moto",
+ "ballet"
+ ],
+ "more": [
+ "robot",
+ "moto_return",
+ "charge",
+ "ballet_male",
+ "gymnast",
+ "powder"
+ ],
+ "clips": [
+ {
+ "key": "berry",
+ "file": "berry.mp4",
+ "frames": 124,
+ "first": 0,
+ "take": "meridian_return_l150_berry_event22",
+ "generated": "videos-all/meridian_return_l150_berry_event22/out.mp4",
+ "input": "videos-all/meridian_return_l150_berry_event22/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/teacher_followups/film_edit_return_v1.json",
+ "hold": [
+ 24,
+ 84
+ ],
+ "graph": "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='PLAY':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,0,23)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='HOLD':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,24,83)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='RESUME':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,84,123)'[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 62
+ },
+ {
+ "key": "moto",
+ "file": "moto.mp4",
+ "frames": 175,
+ "first": 0,
+ "take": "meridian_longtake_t30_moto_dust_retreat25",
+ "generated": "videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4",
+ "input": "videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/longtake_edit/move_manifest.json",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 87
+ },
+ {
+ "key": "ballet",
+ "file": "ballet.mp4",
+ "frames": 96,
+ "first": 24,
+ "take": "meridian_ballet_t30_female_arc",
+ "generated": "videos-all/meridian_ballet_t30_female_arc/out.mp4",
+ "input": "videos-all/overnight/sources/dutch_ballet_female_2575.png",
+ "input_kind": "image",
+ "approved_edit": "videos-all/teacher_followups/film_edit_ballet_v1.json",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=24:end_frame=120,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT IMAGE':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 48
+ },
+ {
+ "key": "moto_return",
+ "file": "moto_return.mp4",
+ "frames": 124,
+ "first": 0,
+ "take": "meridian_motion_l150_moto_event_return30",
+ "generated": "videos-all/meridian_motion_l150_moto_event_return30/out.mp4",
+ "input": "videos-all/meridian_motion_l150_moto_event_return30/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/teacher_followups/film_edit_return_v1.json",
+ "hold": [
+ 24,
+ 84
+ ],
+ "graph": "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='PLAY':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,0,23)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='HOLD':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,24,83)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='RESUME':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,84,123)'[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 62
+ },
+ {
+ "key": "charge",
+ "file": "charge.mp4",
+ "frames": 124,
+ "first": 0,
+ "take": "meridian_material_l150_charge_event_return22",
+ "generated": "videos-all/meridian_material_l150_charge_event_return22/out.mp4",
+ "input": "videos-all/meridian_material_l150_charge_event_return22/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/teacher_followups/film_edit_return_v1.json",
+ "hold": [
+ 24,
+ 106
+ ],
+ "graph": "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='PLAY':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,0,23)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='HOLD':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,24,105)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='RESUME':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,106,123)'[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 62
+ },
+ {
+ "key": "ballet_male",
+ "file": "ballet_male.mp4",
+ "frames": 96,
+ "first": 24,
+ "take": "meridian_ballet_t30_male_lowarc",
+ "generated": "videos-all/meridian_ballet_t30_male_lowarc/out.mp4",
+ "input": "videos-all/overnight/sources/dutch_ballet_male_1900.png",
+ "input_kind": "image",
+ "approved_edit": "videos-all/teacher_followups/film_edit_ballet_v1.json",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=24:end_frame=120,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT IMAGE':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 48
+ },
+ {
+ "key": "gymnast",
+ "file": "gymnast.mp4",
+ "frames": 175,
+ "first": 0,
+ "take": "meridian_longtake_t30_gymnast_pink_rise12",
+ "generated": "videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4",
+ "input": "videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/longtake_edit/move_manifest.json",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 87
+ },
+ {
+ "key": "powder",
+ "file": "powder.mp4",
+ "frames": 175,
+ "first": 0,
+ "take": "meridian_longtake_t30_powder_frontal_rise18",
+ "generated": "videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4",
+ "input": "videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/longtake_edit/move_manifest.json",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 87
+ },
+ {
+ "key": "nba_part_0",
+ "file": "nba_part_0.mp4",
+ "frames": 38,
+ "first": 0,
+ "input": "videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "input_kind": "source_footage",
+ "graph": "[0:v]trim=start_frame=0:end_frame=38,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "kind": "original",
+ "film_start": 0
+ },
+ {
+ "key": "nba_part_1",
+ "file": "nba_part_1.mp4",
+ "frames": 72,
+ "first": 24,
+ "take": "meridian_nba3_l150_moment38_left14",
+ "generated": "videos-all/meridian_nba3_l150_moment38_left14/out.mp4",
+ "input": "videos-all/meridian_nba3_l150_moment38_left14/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "kind": "hero",
+ "film_start": 38
+ },
+ {
+ "key": "nba_part_2",
+ "file": "nba_part_2.mp4",
+ "frames": 15,
+ "first": 39,
+ "input": "videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "input_kind": "source_footage",
+ "graph": "[0:v]trim=start_frame=39:end_frame=54,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "kind": "original",
+ "film_start": 110
+ },
+ {
+ "key": "nba_part_3",
+ "file": "nba_part_3.mp4",
+ "frames": 72,
+ "first": 24,
+ "take": "meridian_nba3_l150_moment54_right14",
+ "generated": "videos-all/meridian_nba3_l150_moment54_right14/out.mp4",
+ "input": "videos-all/meridian_nba3_l150_moment54_right14/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "kind": "hero",
+ "film_start": 125
+ },
+ {
+ "key": "nba_part_4",
+ "file": "nba_part_4.mp4",
+ "frames": 15,
+ "first": 55,
+ "input": "videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "input_kind": "source_footage",
+ "graph": "[0:v]trim=start_frame=55:end_frame=70,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "kind": "original",
+ "film_start": 197
+ },
+ {
+ "key": "nba_part_5",
+ "file": "nba_part_5.mp4",
+ "frames": 72,
+ "first": 24,
+ "generated": [
+ "videos-all/meridian_nba3_l150_air_left14/out.mp4",
+ "videos-all/meridian_nba3_l150_air_right14/out.mp4"
+ ],
+ "input": "videos-all/meridian_nba3_l150_air_left14/source.mp4",
+ "input_kind": "aligned_video",
+ "graph": "[0:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=952:540:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=952:540:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[left];[1:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=952:540:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=952:540:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[right];[left][right]hstack=inputs=2,pad=1920:1088:8:220:color=0x0b0c0c[main];[2:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / SAME INSTANT':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEWS / SAME INSTANT':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='VIEW A':x=28:y=176:fontsize=24:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='VIEW B':x=988:y=176:fontsize=24:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "take": [
+ "meridian_nba3_l150_air_left14",
+ "meridian_nba3_l150_air_right14"
+ ],
+ "kind": "pair",
+ "film_start": 212
+ },
+ {
+ "key": "nba_part_6",
+ "file": "nba_part_6.mp4",
+ "frames": 53,
+ "first": 71,
+ "input": "videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "input_kind": "source_footage",
+ "graph": "[0:v]trim=start_frame=71:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "kind": "original",
+ "film_start": 284
+ },
+ {
+ "key": "nba",
+ "file": "nba.mp4",
+ "frames": 337,
+ "parts": [
+ "nba_part_0",
+ "nba_part_1",
+ "nba_part_2",
+ "nba_part_3",
+ "nba_part_4",
+ "nba_part_5",
+ "nba_part_6"
+ ],
+ "approved_edit": "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "edit": "Same 337 source/generated frames and hard cuts; omitted only the 36-frame brand card.",
+ "poster_frame": 74
+ },
+ {
+ "key": "robot",
+ "file": "robot.mp4",
+ "frames": 124,
+ "first": 0,
+ "take": "va_pi3_hi",
+ "generated": "videos-all/va_pi3_hi/out.mp4",
+ "input": "videos-all/va_pi3_hi/source.mp4",
+ "input_kind": "aligned_video",
+ "approved_edit": "DEMOS.html",
+ "hold": null,
+ "graph": "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "inset_box": [
+ 1460,
+ 784,
+ 436,
+ 280
+ ],
+ "poster_frame": 62
+ }
+ ],
+ "source_sha256": {
+ "videos-all/teacher_followups/film_edit_return_v1.json": "304da2d15fc51c715bd70dae4eaf154e7d4dd4bd328881a245228597ef299b2b",
+ "videos-all/teacher_followups/film_edit_ballet_v1.json": "ee681e33843a4e661c16ec3c4e4812406fe3235d8b947ddd872b0236c7361d66",
+ "videos-all/longtake_edit/move_manifest.json": "e5315f837ef57b16d702da43c1fe306fea5480169d689599a1d7c97c664b004c",
+ "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json": "d244ebf8b68795339285fcadb84a759cdccd7ca06c787b680fb94fc804a2bc1b",
+ "videos-all/meridian_return_l150_berry_event22/out.mp4": "08fbb622a5cfe7ba17ca85d523c626b6e6298e742e24b6282e3b799d33dc0224",
+ "videos-all/meridian_return_l150_berry_event22/source.mp4": "f98f1bd225bfe4baf14eaf90b7ea7243d828f23dfad82307f9d643fbb1b2db32",
+ "videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4": "fa15153f8b204005aa0a92b06ab17cab7ae373584394ad706bcf3f7b8a3ac99e",
+ "videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4": "57ba804b4b0cec7dfe361931a95bbfed5fef6511e053fb96635198fb77107829",
+ "videos-all/meridian_ballet_t30_female_arc/out.mp4": "42d5b7ffc39418474cdd845dcfc8e4d5e65f6a892b88dd077596d21c24e1f3e8",
+ "videos-all/overnight/sources/dutch_ballet_female_2575.png": "e3a7b9ca86655cba6536d46b95b99ebbd29d1ab7108d23d6e442588df013bf65",
+ "videos-all/meridian_motion_l150_moto_event_return30/out.mp4": "c1b466a1182547c66776e24220c4be16f673cf99f1d0486c6dee359fefab1870",
+ "videos-all/meridian_motion_l150_moto_event_return30/source.mp4": "4627087a4251d37b262f9abcfb6b00c8cbc71b2c0224aef8763fe108b849f8d0",
+ "videos-all/meridian_material_l150_charge_event_return22/out.mp4": "0efd7b01b650bddaa6f3476a22d7c830f2b54bb3e807e30c717e144e2ffebb7d",
+ "videos-all/meridian_material_l150_charge_event_return22/source.mp4": "42cc7f068d27624227070719d32e66bb9a96f74d5483b25c0d8cdd6d0c26182f",
+ "videos-all/meridian_ballet_t30_male_lowarc/out.mp4": "fc70f089a626404a3720943f6d720fd9bfe34f8dd5d071717e25665a66948fe8",
+ "videos-all/overnight/sources/dutch_ballet_male_1900.png": "214085bb2bda88513af97eca9b0535dde0a2f8592014d4163efb5d7609e07ced",
+ "videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4": "4285c59b5c964b83c5ba782950ae3f930f6dd213b85dea9837bdbdcf94174b09",
+ "videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4": "0db2bcf81426da121b987994c85aea5ce6c616b447d98daf89b49e24758454c5",
+ "videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4": "76356a28f687516e3470d5e915c82eb38b9841ae88a2951ecaf9aac95179aac8",
+ "videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4": "e05e9b8d7927c5f0ee935c1426d779fe91cd0881a40f0568795074ad163b93b7",
+ "videos-all/nba3_teacher30/nba3_full_event.mp4": "5d055116a5081a6a8d07dbd1f285fe99d1591e040dd9d27faee65af548085313",
+ "videos-all/meridian_nba3_l150_moment38_left14/out.mp4": "dd3ae581a8a3ed5b9d078765deb74c65eba3050a0029609608ba838806996079",
+ "videos-all/meridian_nba3_l150_moment38_left14/source.mp4": "b6de091414e968e827394232e1e97fb8934344738fa3961a086346a3d63a1b50",
+ "videos-all/meridian_nba3_l150_moment54_right14/out.mp4": "bcabd1bcf2204bcdb1df51c267c3f15b3eef7a9c9d6130d5eeff259d42ec7b5b",
+ "videos-all/meridian_nba3_l150_moment54_right14/source.mp4": "739c9b25f3f3a81609a97124580b299fc4caeec924da9c5cf2dd0ef15aaafe69",
+ "videos-all/meridian_nba3_l150_air_left14/out.mp4": "ab51eaf579ca34aba20ab110db79cd5bd9381505b653a6a380837378c9105662",
+ "videos-all/meridian_nba3_l150_air_right14/out.mp4": "998230f1881ee760b55c8f09899c4488700655ca54fa7115fdd2bf5910842dc5",
+ "videos-all/meridian_nba3_l150_air_left14/source.mp4": "f062e62ff9216ce911c49ff323c5763b741a7c5a334e1e319cff569c6f8dd26a",
+ "videos-all/va_pi3_hi/out.mp4": "b969232c38d149ecc880513eb8b291bbf8d428bc5ff916492d426a0dc0348238",
+ "videos-all/va_pi3_hi/source.mp4": "ae4257c88de563e6ccbba39ef13f03ecb6079d5814a758da0cc7e5863f2bc5ab",
+ "DEMOS.html": "ecf36ae700d4a43a3c6fa379893299f0362eb2812f474125e41170ef3a91a312"
+ },
+ "edit": "Fixed bottom-right input inset. Native 24 fps, exact approved output intervals, fit/pad only; no output crop, repair, interpolation or new inference. H.264 CRF17 re-encode.",
+ "input_timing": "Video insets use matching frame indices of each take's source.mp4, including holds. Ballet insets use the actual static PNG input. NBA source-footage portions have explicit labels and no redundant inset.",
+ "scope": "Local research only. Source permissions and quality limitations remain as recorded in the linked original edit notes.",
+ "commands": [
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_return_l150_berry_event22/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_return_l150_berry_event22/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='PLAY':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,0,23)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='HOLD':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,24,83)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='RESUME':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,84,123)'[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "124",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/berry.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "175",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/moto.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_ballet_t30_female_arc/out.mp4",
+ "-loop",
+ "1",
+ "-framerate",
+ "24",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/overnight/sources/dutch_ballet_female_2575.png",
+ "-filter_complex",
+ "[0:v]trim=start_frame=24:end_frame=120,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT IMAGE':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "96",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/ballet.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_motion_l150_moto_event_return30/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_motion_l150_moto_event_return30/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='PLAY':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,0,23)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='HOLD':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,24,83)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='RESUME':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,84,123)'[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "124",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/moto_return.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_material_l150_charge_event_return22/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_material_l150_charge_event_return22/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='PLAY':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,0,23)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='HOLD':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,24,105)',drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='RESUME':x=w-tw-28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10:enable='between(n,106,123)'[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "124",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/charge.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_ballet_t30_male_lowarc/out.mp4",
+ "-loop",
+ "1",
+ "-framerate",
+ "24",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/overnight/sources/dutch_ballet_male_1900.png",
+ "-filter_complex",
+ "[0:v]trim=start_frame=24:end_frame=120,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT IMAGE':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "96",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/ballet_male.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "175",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/gymnast.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=175,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "175",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/powder.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=38,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "38",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_part_0.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_nba3_l150_moment38_left14/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_nba3_l150_moment38_left14/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "72",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_part_1.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=39:end_frame=54,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "15",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_part_2.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_nba3_l150_moment54_right14/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_nba3_l150_moment54_right14/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "72",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_part_3.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=55:end_frame=70,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "15",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_part_4.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_nba3_l150_air_left14/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_nba3_l150_air_right14/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/meridian_nba3_l150_air_left14/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=952:540:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=952:540:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[left];[1:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=952:540:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=952:540:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[right];[left][right]hstack=inputs=2,pad=1920:1088:8:220:color=0x0b0c0c[main];[2:v]trim=start_frame=24:end_frame=96,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / SAME INSTANT':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEWS / SAME INSTANT':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='VIEW A':x=28:y=176:fontsize=24:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='VIEW B':x=988:y=176:fontsize=24:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "72",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_part_5.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=71:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='SOURCE FOOTAGE / NOT GENERATED':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "53",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_part_6.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-f",
+ "concat",
+ "-safe",
+ "0",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba_concat.txt",
+ "-an",
+ "-c",
+ "copy",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/berry.mp4",
+ "-vf",
+ "select=eq(n\\,62)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/berry.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/moto.mp4",
+ "-vf",
+ "select=eq(n\\,87)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/moto.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/ballet.mp4",
+ "-vf",
+ "select=eq(n\\,48)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/ballet.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/moto_return.mp4",
+ "-vf",
+ "select=eq(n\\,62)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/moto_return.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/charge.mp4",
+ "-vf",
+ "select=eq(n\\,62)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/charge.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/ballet_male.mp4",
+ "-vf",
+ "select=eq(n\\,48)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/ballet_male.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/gymnast.mp4",
+ "-vf",
+ "select=eq(n\\,87)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/gymnast.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/powder.mp4",
+ "-vf",
+ "select=eq(n\\,87)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/powder.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba.mp4",
+ "-vf",
+ "select=eq(n\\,74)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/nba.jpg"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/va_pi3_hi/out.mp4",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/va_pi3_hi/source.mp4",
+ "-filter_complex",
+ "[0:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=1920:1088:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=1920:1088:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1[main];[1:v]trim=start_frame=0:end_frame=124,setpts=N/(24*TB),scale=432:244:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos,pad=432:244:(ow-iw)/2:(oh-ih)/2:color=0x0b0c0c,setsar=1,pad=436:280:2:34:color=0x191c1a,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='INPUT / ALIGNED TIME':x=12:y=8:fontsize=20:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[input];[main][input]overlay=1460:784:shortest=1,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='GENERATED VIEW':x=28:y=28:fontsize=28:fontcolor=0xeeeae1:box=1:boxcolor=black@0.5:boxborderw=10[final]",
+ "-map",
+ "[final]",
+ "-frames:v",
+ "124",
+ "-an",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "17",
+ "-pix_fmt",
+ "yuv420p",
+ "-threads",
+ "2",
+ "-r",
+ "24",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/robot.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-nostdin",
+ "-v",
+ "error",
+ "-n",
+ "-threads",
+ "2",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/robot.mp4",
+ "-vf",
+ "select=eq(n\\,62)",
+ "-frames:v",
+ "1",
+ "-threads",
+ "2",
+ "-q:v",
+ "2",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/research_examples_v1/robot.jpg"
+ ]
+ ]
+}
diff --git a/videos-all/research_examples_v1/moto.jpg b/videos-all/research_examples_v1/moto.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..cdced4939fceb108edefead85b0f9835e435c31d
--- /dev/null
+++ b/videos-all/research_examples_v1/moto.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e1b97396ca746e787182b216c67760d97a6f710d4795fda3c423701ff159090b
+size 244937
diff --git a/videos-all/research_examples_v1/moto.mp4 b/videos-all/research_examples_v1/moto.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..1ec3dc1cd1914ae15b303821ca8551c46b3520fb
--- /dev/null
+++ b/videos-all/research_examples_v1/moto.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f98657a8a60ca942afec98d7a1d692cd9b5ca0f4903f42c9d6714866ad9a9013
+size 5232889
diff --git a/videos-all/research_examples_v1/moto_return.jpg b/videos-all/research_examples_v1/moto_return.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..772577adf032e635ce7d34e2c27f8d4f8c09bdb2
--- /dev/null
+++ b/videos-all/research_examples_v1/moto_return.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e0721b16e90fdd2a5dd5702a41f48773f262eb87eb4e3fa7d3ac2742ff7633e2
+size 222045
diff --git a/videos-all/research_examples_v1/moto_return.mp4 b/videos-all/research_examples_v1/moto_return.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..9da4ab05f52f5e55113e829c42a7607de21775b6
--- /dev/null
+++ b/videos-all/research_examples_v1/moto_return.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13b17cf823c0ab15aec6a18581bfd76b0d67d599b0a212c89d3128c84d8004d8
+size 4564448
diff --git a/videos-all/research_examples_v1/nba.jpg b/videos-all/research_examples_v1/nba.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c57d9c56fc483fd3df5025eb35eecbcfa7164f9f
--- /dev/null
+++ b/videos-all/research_examples_v1/nba.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b404878fef8926a65dc825192de4621383453baa4943625d7125c023e93d8938
+size 348306
diff --git a/videos-all/research_examples_v1/nba.mp4 b/videos-all/research_examples_v1/nba.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..edb5534d453e111ea5f8f0a2db03c0a60404df3d
--- /dev/null
+++ b/videos-all/research_examples_v1/nba.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:36714fcb920dc751f4bb7486c582c912642a462035852f886ef0275fd4788bc9
+size 16937847
diff --git a/videos-all/research_examples_v1/powder.jpg b/videos-all/research_examples_v1/powder.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..91e64a1c3075fe88ab06679fc32889b4b44b9618
--- /dev/null
+++ b/videos-all/research_examples_v1/powder.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4ec146524622da945cfcac4874274d3252c0560bdd1392627762266538f6ecb8
+size 162553
diff --git a/videos-all/research_examples_v1/powder.mp4 b/videos-all/research_examples_v1/powder.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..4dcf866466ad8323886c1c1101d8d542f41655c0
--- /dev/null
+++ b/videos-all/research_examples_v1/powder.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8c672aa8682b4da6d8c6de9f1b1142643c0ceaf08c8f0ede9e4e6715021de082
+size 3013928
diff --git a/videos-all/research_examples_v1/robot.jpg b/videos-all/research_examples_v1/robot.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..5c201730dade1b5f0278444d61b2940d1c1d4df4
--- /dev/null
+++ b/videos-all/research_examples_v1/robot.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d594e9b228652c6193f0be5492ff27e977dbf7b5e4fd838871986d401d8d9798
+size 212084
diff --git a/videos-all/research_examples_v1/robot.mp4 b/videos-all/research_examples_v1/robot.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..1db904f532632eb08cfff2c2ebdcc4e83e78ab41
--- /dev/null
+++ b/videos-all/research_examples_v1/robot.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c6646563d7c50656ffd6914f8eff30096cde212ccdab849e457d1ea96adc3b89
+size 3021691
diff --git a/videos-all/research_examples_v1/validation.json b/videos-all/research_examples_v1/validation.json
new file mode 100644
index 0000000000000000000000000000000000000000..e5fa93993236271c251580ab0686255cb779610a
--- /dev/null
+++ b/videos-all/research_examples_v1/validation.json
@@ -0,0 +1,275 @@
+{
+ "source_hashes_unchanged": [
+ "videos-all/teacher_followups/film_edit_return_v1.json",
+ "videos-all/teacher_followups/film_edit_ballet_v1.json",
+ "videos-all/longtake_edit/move_manifest.json",
+ "videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json",
+ "videos-all/meridian_return_l150_berry_event22/out.mp4",
+ "videos-all/meridian_return_l150_berry_event22/source.mp4",
+ "videos-all/meridian_longtake_t30_moto_dust_retreat25/out.mp4",
+ "videos-all/meridian_longtake_t30_moto_dust_retreat25/source.mp4",
+ "videos-all/meridian_ballet_t30_female_arc/out.mp4",
+ "videos-all/overnight/sources/dutch_ballet_female_2575.png",
+ "videos-all/meridian_motion_l150_moto_event_return30/out.mp4",
+ "videos-all/meridian_motion_l150_moto_event_return30/source.mp4",
+ "videos-all/meridian_material_l150_charge_event_return22/out.mp4",
+ "videos-all/meridian_material_l150_charge_event_return22/source.mp4",
+ "videos-all/meridian_ballet_t30_male_lowarc/out.mp4",
+ "videos-all/overnight/sources/dutch_ballet_male_1900.png",
+ "videos-all/meridian_longtake_t30_gymnast_pink_rise12/out.mp4",
+ "videos-all/meridian_longtake_t30_gymnast_pink_rise12/source.mp4",
+ "videos-all/meridian_longtake_t30_powder_frontal_rise18/out.mp4",
+ "videos-all/meridian_longtake_t30_powder_frontal_rise18/source.mp4",
+ "videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "videos-all/meridian_nba3_l150_moment38_left14/out.mp4",
+ "videos-all/meridian_nba3_l150_moment38_left14/source.mp4",
+ "videos-all/meridian_nba3_l150_moment54_right14/out.mp4",
+ "videos-all/meridian_nba3_l150_moment54_right14/source.mp4",
+ "videos-all/meridian_nba3_l150_air_left14/out.mp4",
+ "videos-all/meridian_nba3_l150_air_right14/out.mp4",
+ "videos-all/meridian_nba3_l150_air_left14/source.mp4",
+ "videos-all/va_pi3_hi/out.mp4",
+ "videos-all/va_pi3_hi/source.mp4",
+ "DEMOS.html"
+ ],
+ "media": {
+ "berry": {
+ "frames": 124,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "moto": {
+ "frames": 175,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "ballet": {
+ "frames": 96,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "moto_return": {
+ "frames": 124,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "charge": {
+ "frames": 124,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "ballet_male": {
+ "frames": 96,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "gymnast": {
+ "frames": 175,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "powder": {
+ "frames": 175,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba_part_0": {
+ "frames": 38,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba_part_1": {
+ "frames": 72,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba_part_2": {
+ "frames": 15,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba_part_3": {
+ "frames": 72,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba_part_4": {
+ "frames": 15,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba_part_5": {
+ "frames": 72,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba_part_6": {
+ "frames": 53,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "nba": {
+ "frames": 337,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ },
+ "robot": {
+ "frames": 124,
+ "fps": 24,
+ "full_decode": true,
+ "exact_pts": true
+ }
+ },
+ "inset_samples": [
+ {
+ "clip": "berry",
+ "frame": 62,
+ "input_frame": 62,
+ "rgb_mse": 2.7733
+ },
+ {
+ "clip": "berry",
+ "frame": 23,
+ "input_frame": 23,
+ "rgb_mse": 7.6111
+ },
+ {
+ "clip": "berry",
+ "frame": 84,
+ "input_frame": 84,
+ "rgb_mse": 5.3158
+ },
+ {
+ "clip": "moto",
+ "frame": 87,
+ "input_frame": 87,
+ "rgb_mse": 5.5141
+ },
+ {
+ "clip": "ballet",
+ "frame": 48,
+ "input_frame": 0,
+ "rgb_mse": 0.6925
+ },
+ {
+ "clip": "moto_return",
+ "frame": 62,
+ "input_frame": 62,
+ "rgb_mse": 3.1775
+ },
+ {
+ "clip": "moto_return",
+ "frame": 23,
+ "input_frame": 23,
+ "rgb_mse": 6.9962
+ },
+ {
+ "clip": "moto_return",
+ "frame": 84,
+ "input_frame": 84,
+ "rgb_mse": 5.1047
+ },
+ {
+ "clip": "charge",
+ "frame": 62,
+ "input_frame": 62,
+ "rgb_mse": 2.0825
+ },
+ {
+ "clip": "charge",
+ "frame": 23,
+ "input_frame": 23,
+ "rgb_mse": 5.0717
+ },
+ {
+ "clip": "charge",
+ "frame": 106,
+ "input_frame": 106,
+ "rgb_mse": 4.9533
+ },
+ {
+ "clip": "ballet_male",
+ "frame": 48,
+ "input_frame": 0,
+ "rgb_mse": 0.4587
+ },
+ {
+ "clip": "gymnast",
+ "frame": 87,
+ "input_frame": 87,
+ "rgb_mse": 2.2202
+ },
+ {
+ "clip": "powder",
+ "frame": 87,
+ "input_frame": 87,
+ "rgb_mse": 3.6368
+ },
+ {
+ "clip": "nba_part_1",
+ "frame": 36,
+ "input_frame": 60,
+ "rgb_mse": 4.0886
+ },
+ {
+ "clip": "nba_part_3",
+ "frame": 36,
+ "input_frame": 60,
+ "rgb_mse": 4.1241
+ },
+ {
+ "clip": "nba_part_5",
+ "frame": 36,
+ "input_frame": 60,
+ "rgb_mse": 3.984
+ },
+ {
+ "clip": "robot",
+ "frame": 62,
+ "input_frame": 62,
+ "rgb_mse": 5.7323
+ }
+ ],
+ "browser_playback": "Not verified: Chromium startup is blocked by the environment sandbox.",
+ "continuous_motion_review": false,
+ "nba_concat_frames_identical_to_parts": true,
+ "approved_film_intervals_and_hold_labels_match": true,
+ "page": {
+ "markdown_html_parity": true,
+ "local_assets_and_links_exist": true,
+ "duplicate_ids": false,
+ "main_examples": 4,
+ "collapsed_examples": 6,
+ "total_players_including_teaser_and_studio": 12,
+ "autoplay": false,
+ "default_visible_article_words_including_captions": 520,
+ "layout": "Original compact two-column demo grid; one column on mobile."
+ },
+ "sampled_visual_review": [
+ "nba.jpg",
+ "berry.jpg",
+ "moto.jpg",
+ "ballet.jpg",
+ "robot.jpg",
+ "NBA generated pair at film frame 248",
+ "NBA labeled source completion at film frame 310"
+ ],
+ "approved_move_intervals_match": true,
+ "edit_notes_local_links_exist": true
+}
diff --git a/videos-all/research_examples_v2/README.md b/videos-all/research_examples_v2/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..cfd97d132ba6ad90375529a67ade1f57cef889f8
--- /dev/null
+++ b/videos-all/research_examples_v2/README.md
@@ -0,0 +1,49 @@
+# Research examples: camera composition and a single image
+
+Selected for the README and [research page](../../docs/research.md) on 14 September 2026.
+Both videos are existing results selected by the user, not new inference runs. The original MP4s
+are embedded unchanged; only new poster frames were extracted at 2.5 seconds.
+
+## Compose a camera path
+
+[Watch the compound-camera example](../teaser_meridian_compound_motor_dust_explained_v1.mp4)
+— 243 frames, 24 fps, 10.125 seconds.
+
+One uncut generation: widen, orbit, slide right, counter-orbit, approach, and retreat while source
+time advances. The existing presentation includes the selected model-input video, stage labels,
+and requested camera diagrams. Those diagrams describe the authored path, not measured camera
+motion in the generated result. The source clock refers to the prepared input, not original capture time.
+
+[Time-aligned input](../longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/source.mp4)
+· [Unoverlaid output](../longtake_edit/multisegment/work_gpu3/takes/1789313901_4e9dd3_11/out.mp4).
+The native 1344 × 768 output sits on the explainer's 1920 × 1080 canvas; it is not a native 1080p generation.
+
+This replaces the old main motocross card. The similar **Dust in suspension** card is removed
+from the supplementary gallery; its archived files remain available.
+
+## One image. Another viewpoint.
+
+[Watch the ballet example](../meridian_ballet_l150_female_reverse45.mp4)
+— 124 frames, 24 fps, approximately 5.17 seconds.
+
+[Actual single-image input](../overnight/sources/dutch_ballet_female_2575.png)
+· [Unoverlaid output](../meridian_ballet_l150_female_reverse45/out.mp4).
+The source is one extracted ballet frame, not a moving dance clip. Generation uses that same image
+throughout (`--freeze 0:124`), with a requested 45° camera sweep. The file name's `reverse45` does
+not mean reverse source playback. The selected presentation already has a lower-left camera diagram;
+the page shows only that video, without a separate input-image thumbnail. The input is documented
+here for provenance. No additional overlay or retiming has been applied.
+
+## Other examples and source credits
+
+NBA, strawberries, robots, animation, male ballet, gymnastics, and snow sports retain the
+[original selections, inputs, and edit notes](../research_examples_v1/README.md).
+
+- Motocross: Jacob + Katie Schwarz / Mystery Box LLC (2014), copyright reserved.
+- Ballet: Altin Kaftira / ArtAlt; Dutch ballet frame 2575 is the still input.
+
+Public promotional clearance for these sources is not established. This remains a private research
+preview. Generated surfaces, fine details, and stage completion can contain artifacts.
+
+[File hashes and technical checks](manifest.json) record this replacement. Full decoding and sampled
+frame inspection are not a continuous human motion review or an authenticated browser playback test.
diff --git a/videos-all/research_examples_v2/ballet_reverse45.jpg b/videos-all/research_examples_v2/ballet_reverse45.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e60caa09a6e4440ed06db8c3811bf4932a4d56f4
Binary files /dev/null and b/videos-all/research_examples_v2/ballet_reverse45.jpg differ
diff --git a/videos-all/research_examples_v2/manifest.json b/videos-all/research_examples_v2/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..f7662b80217e6181c2efe7d78f3beaaff27abcee
--- /dev/null
+++ b/videos-all/research_examples_v2/manifest.json
@@ -0,0 +1,61 @@
+{
+ "updated": "2026-09-14",
+ "selected_videos": [
+ {
+ "path": "videos-all/teaser_meridian_compound_motor_dust_explained_v1.mp4",
+ "sha256": "3b286a819ac1ae48a634bb52932f49b0b28741529a0c4ada9c709881489beb24",
+ "bytes": 10845186,
+ "frames": 243,
+ "fps": 24,
+ "width": 1920,
+ "height": 1080,
+ "seconds": 10.125,
+ "full_decode": true,
+ "faststart": true,
+ "original_bytes_unchanged": true
+ },
+ {
+ "path": "videos-all/meridian_ballet_l150_female_reverse45.mp4",
+ "sha256": "f4d0709082e46d607f06bafb201e5cef2c69325fd7c234d2d23d8154bd4c21b8",
+ "bytes": 1263368,
+ "frames": 124,
+ "fps": 24,
+ "width": 1920,
+ "height": 1088,
+ "seconds": 5.167,
+ "full_decode": true,
+ "faststart": true,
+ "original_bytes_unchanged": true
+ }
+ ],
+ "poster_frames": {
+ "videos-all/research_examples_v2/motor_compound.jpg": {
+ "source": "videos-all/teaser_meridian_compound_motor_dust_explained_v1.mp4",
+ "seconds": 2.5
+ },
+ "videos-all/research_examples_v2/ballet_reverse45.jpg": {
+ "source": "videos-all/meridian_ballet_l150_female_reverse45.mp4",
+ "seconds": 2.5
+ }
+ },
+ "ballet_input": "videos-all/overnight/sources/dutch_ballet_female_2575.png",
+ "ballet_input_placement": "not displayed separately on the page; source retained in provenance; original video unchanged",
+ "main_order": [
+ "nba-film",
+ "berry-film",
+ "moto-film",
+ "ballet-film"
+ ],
+ "supplementary_order": [
+ "robot-film",
+ "charge-film",
+ "ballet_male-film",
+ "gymnast-film",
+ "powder-film"
+ ],
+ "sampled_frames_reviewed": true,
+ "continuous_human_motion_review": false,
+ "browser_playback_tested": false,
+ "file_links_checked": 210,
+ "private_only": true
+}
diff --git a/videos-all/research_examples_v2/motor_compound.jpg b/videos-all/research_examples_v2/motor_compound.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..636f3596976948a491d60b00c9acdc209d5a4282
--- /dev/null
+++ b/videos-all/research_examples_v2/motor_compound.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:16bc357a4514e50c03e23bf23e3552f453502856d51c7a682ddad0f7b2fc707c
+size 265435
diff --git a/videos-all/return_showcase/README.md b/videos-all/return_showcase/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..911fae5edd5fdbd03f80b7819c9971ae8b481e1a
--- /dev/null
+++ b/videos-all/return_showcase/README.md
@@ -0,0 +1,28 @@
+# Meridian / Explore the moment. Let time continue.
+
+[Watch the17-second film](preview.html) · [MP4](../teaser_meridian_return_v1.mp4) · [Exact edit](../teacher_followups/film_edit_return_v1.json) · [Selection](selection.json)
+
+Three complete LoRA150 takes, not a video played forward and backward. Each event advances, holds while the camera offset explores, then resumes. The output always plays at its native24fps.
+
+| Film frames | Scene | Raw output | Source time | Time design |
+|---|---|---|---|---|
+|0–123|Strawberries|0–123|17–19.666667s|24 play /60 hold at18s /40 resume|
+|124–247|Motocross dust|0–123|354.228–356.898s|24 play /60 hold at355.229s /40 resume|
+|248–371|Charge, animated|0–123|84–85.750s|24 play /82 hold at85s /18 resume|
+|372–407|Meridian card|—|—|36 frames|
+
+Full200 + LoRA150 /4 steps / shift3 / seed1234.1920×1080,408 frames,24fps, silent. No output crop, retiming, reversal, interpolation, repair, stabilization or upscaling. Uniform reduction to fit the editorial layout only. Model input is the prepared conditioning image/video, not an assertion of uncropped camera-original footage; exact inference boxes and provenance are in the edit.
+
+## What the path means
+
+The plot is **source-relative conditioning**, computed from `inv(c2w_src[n]) @ c2w_dst[n]`, translation normalized by scene depth. Its offset returns to identity at the final frame. The source camera itself can move, so the absolute target camera does **not** necessarily return to its first world-space pose. Plan views omit height. This is not measured output motion, verified geometry or an identity-recovery benchmark. [Recorded-array verification](review/control_verification.json).
+
+## Review and limits
+
+All32 distributed samples of each raw take, native peak and endpoints, and native play/hold/resume boundaries were inspected. Fine seeds, dust, bike parts, faces, props and newly exposed geometry remain soft or inferred. The teacher macro-event reference was rejected for an invented blue structure at mid-path; this film retains the cleaner LoRA take. Full film decode, exact frame timestamps, cut-boundary and browser records live in `review/`. Sampled inspection and browser playback tests are not continuous visual-quality certification.
+
+## Sources / local research only
+
+- Strawberries: [Mixkit101338](https://mixkit.co/free-stock-video/strawberries-splashing-in-slow-motion-101338/), Stock Video Free License listed on the retained item page. [Preparation and hash](../berry_time/README.md). Source is already slow motion; displayed time is published-file PTS, not physical capture time.
+- Motocross: [Phantom sports film](https://www.youtube.com/watch?v=13wt6cmCRK0), Jacob + Katie Schwarz, ©2014 Mystery Box LLC. [Retained provenance](../phantom_motion/README.md). Already slow motion; published-file PTS. Public promotional rights are not established: local research, no upload or endorsement.
+- Charge2022: ©Blender Foundation, CC BY4.0. [Source and preparation](../directed_materials/README.md). Animated film, not real-world capture; modified generated viewpoints.
diff --git a/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/edit.json b/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/edit.json
new file mode 100644
index 0000000000000000000000000000000000000000..6749d2f1c32c6739bbb67171746bf62d29a7439d
--- /dev/null
+++ b/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/edit.json
@@ -0,0 +1,502 @@
+{
+ "output": "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise.mp4",
+ "output_frames": 907,
+ "fps": 24,
+ "seconds": 37.791666666666664,
+ "shots": [
+ {
+ "name": "01_title",
+ "frames": 60,
+ "title": "Meridian Studio",
+ "subtitle": "Compose space and time.",
+ "card": true,
+ "note": "A preview-only walkthrough",
+ "output_start_frame": 0
+ },
+ {
+ "name": "02_source",
+ "frames": 124,
+ "file": "input.mp4",
+ "start": 0,
+ "crop": null,
+ "title": "Start with one event.",
+ "subtitle": "A single source video.",
+ "chapter": "01 / SOURCE",
+ "note": "NBA3 / supplied source footage",
+ "output_start_frame": 60
+ },
+ {
+ "name": "03_workspace",
+ "frames": 96,
+ "file": "studio_walkthrough_review.mp4",
+ "start": 7.0,
+ "crop": [
+ 360,
+ 286,
+ 1200,
+ 630
+ ],
+ "title": "Design the observation.",
+ "subtitle": "Source geometry. Camera paths. One workspace.",
+ "chapter": "02 / SPACE",
+ "note": "Recorded Studio UI / authoring and backend waits omitted between excerpts",
+ "output_start_frame": 184
+ },
+ {
+ "name": "04_position",
+ "frames": 72,
+ "file": "studio_walkthrough_review.mp4",
+ "start": 271.0,
+ "crop": [
+ 1024,
+ 0,
+ 536,
+ 424
+ ],
+ "title": "Shape the camera.",
+ "subtitle": "Move the viewpoint. Refine the aim.",
+ "chapter": "02 / SPACE",
+ "note": "Live 3D editor / recorded pointer gesture / not generative rendering",
+ "output_start_frame": 280
+ },
+ {
+ "name": "05_aim",
+ "frames": 72,
+ "file": "studio_walkthrough_review.mp4",
+ "start": 280.6,
+ "crop": [
+ 1024,
+ 0,
+ 536,
+ 424
+ ],
+ "title": "Shape the camera.",
+ "subtitle": "Move the viewpoint. Refine the aim.",
+ "chapter": "02 / SPACE",
+ "note": "Live 3D editor / backend wait omitted at this cut",
+ "output_start_frame": 352
+ },
+ {
+ "name": "06_time",
+ "frames": 168,
+ "file": "studio_walkthrough_review.mp4",
+ "start": 346.0,
+ "crop": [
+ 380,
+ 448,
+ 1176,
+ 632
+ ],
+ "title": "Hold the moment.",
+ "subtitle": "Keep the camera moving.",
+ "chapter": "03 / TIME",
+ "note": "Source frame 60 / four camera keys / different output times",
+ "output_start_frame": 424
+ },
+ {
+ "name": "07_reference",
+ "frames": 243,
+ "file": "preview_truth.mp4",
+ "start": 0,
+ "crop": null,
+ "title": "Preview before you generate.",
+ "subtitle": "One continuous geometric reference.",
+ "chapter": "04 / PREVIEW",
+ "note": "Geometry only / grey marks missing source coverage / not generated video",
+ "output_start_frame": 592
+ },
+ {
+ "name": "08_close",
+ "frames": 72,
+ "title": "Compose first. Generate next.",
+ "subtitle": "Meridian Studio / included in the code release",
+ "card": true,
+ "note": "Preview-only walkthrough / final generation not shown",
+ "output_start_frame": 835
+ }
+ ],
+ "input_sha256": {
+ "input.mp4": "5d055116a5081a6a8d07dbd1f285fe99d1591e040dd9d27faee65af548085313",
+ "preview_truth.mp4": "f03e40a4be4591979ff2b52d4da483afb1e12a99a43d52118f5a26f8164113e6",
+ "studio_walkthrough_review.mp4": "fa3992c190f3f537c6a7a1d4d59122d32c546c1f28eed1742dfbcb3a1cf53ecb"
+ },
+ "output_sha256": "3bf2e235da33464c443754dac8b31d3de92cedda27fd49f38bc898a71050ec7c",
+ "edit_notes": [
+ "Actual recorded UI excerpts; no injected cursor, simulated UI or generated take.",
+ "Authoring steps and backend waits are omitted between excerpts and disclosed on screen.",
+ "Excerpts play at their recorded pace; 25 fps UI capture is resampled to 24 fps.",
+ "Complete 124-frame supplied input and 243-frame geometric reference retained at 24 fps.",
+ "Editorial crops enlarge UI details only. The source and geometric-reference images are uncropped.",
+ "Silent, without narration or music. Original review MP4 and raw WebM are unchanged.",
+ "User-supplied NBA footage; public redistribution rights have not been established.",
+ "Concat list uses exact frame-count durations to avoid container millisecond rounding at edit points."
+ ],
+ "commands": [
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=2.500000000",
+ "-filter_complex",
+ "[0:v]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=(w-tw)/2:y=300:fontsize=23:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Meridian Studio':x=(w-tw)/2:y=424:fontsize=82:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Compose space and time.':x=(w-tw)/2:y=542:fontsize=32:fontcolor=0x9ca7b0,drawbox=x=925:y=634:w=70:h=2:color=0x9fbfc9:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='A preview-only walkthrough':x=(w-tw)/2:y=964:fontsize=21:fontcolor=0x9ca7b0,fade=t=in:st=0:d=0.5,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "60",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/01_title.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=5.166666667",
+ "-threads",
+ "2",
+ "-ss",
+ "0",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/input.mp4",
+ "-filter_complex",
+ "[1:v]fps=24,trim=end_frame=124,setpts=PTS-STARTPTS,scale=w=1536:h=768:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos:out_color_matrix=bt709,setsar=1[detail];[0:v][detail]overlay=x=(W-w)/2:y=218+(768-h)/2:shortest=1[base];[base]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=96:y=40:fontsize=20:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='01 / SOURCE':x=w-tw-96:y=40:fontsize=20:fontcolor=0x9ca7b0,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Start with one event.':x=96:y=86:fontsize=54:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='A single source video.':x=98:y=150:fontsize=27:fontcolor=0x9ca7b0,drawbox=x=96:y=194:w=1728:h=1:color=0x29313a:t=fill,drawbox=x=96:y=1008:w=1728:h=1:color=0x29313a:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='NBA3 / supplied source footage':x=96:y=1030:fontsize=20:fontcolor=0x9ca7b0,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "124",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/02_source.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=4.000000000",
+ "-threads",
+ "2",
+ "-ss",
+ "7.0",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_review.mp4",
+ "-filter_complex",
+ "[1:v]crop=1200:630:360:286,fps=24,trim=end_frame=96,setpts=PTS-STARTPTS,scale=w=1536:h=768:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos:out_color_matrix=bt709,setsar=1[detail];[0:v][detail]overlay=x=(W-w)/2:y=218+(768-h)/2:shortest=1[base];[base]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=96:y=40:fontsize=20:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='02 / SPACE':x=w-tw-96:y=40:fontsize=20:fontcolor=0x9ca7b0,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Design the observation.':x=96:y=86:fontsize=54:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Source geometry. Camera paths. One workspace.':x=98:y=150:fontsize=27:fontcolor=0x9ca7b0,drawbox=x=96:y=194:w=1728:h=1:color=0x29313a:t=fill,drawbox=x=96:y=1008:w=1728:h=1:color=0x29313a:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Recorded Studio UI / authoring and backend waits omitted between excerpts':x=96:y=1030:fontsize=20:fontcolor=0x9ca7b0,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "96",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/03_workspace.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=3.000000000",
+ "-threads",
+ "2",
+ "-ss",
+ "271.0",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_review.mp4",
+ "-filter_complex",
+ "[1:v]crop=536:424:1024:0,fps=24,trim=end_frame=72,setpts=PTS-STARTPTS,scale=w=1536:h=768:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos:out_color_matrix=bt709,setsar=1[detail];[0:v][detail]overlay=x=(W-w)/2:y=218+(768-h)/2:shortest=1[base];[base]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=96:y=40:fontsize=20:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='02 / SPACE':x=w-tw-96:y=40:fontsize=20:fontcolor=0x9ca7b0,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Shape the camera.':x=96:y=86:fontsize=54:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Move the viewpoint. Refine the aim.':x=98:y=150:fontsize=27:fontcolor=0x9ca7b0,drawbox=x=96:y=194:w=1728:h=1:color=0x29313a:t=fill,drawbox=x=96:y=1008:w=1728:h=1:color=0x29313a:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Live 3D editor / recorded pointer gesture / not generative rendering':x=96:y=1030:fontsize=20:fontcolor=0x9ca7b0,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "72",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/04_position.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=3.000000000",
+ "-threads",
+ "2",
+ "-ss",
+ "280.6",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_review.mp4",
+ "-filter_complex",
+ "[1:v]crop=536:424:1024:0,fps=24,trim=end_frame=72,setpts=PTS-STARTPTS,scale=w=1536:h=768:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos:out_color_matrix=bt709,setsar=1[detail];[0:v][detail]overlay=x=(W-w)/2:y=218+(768-h)/2:shortest=1[base];[base]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=96:y=40:fontsize=20:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='02 / SPACE':x=w-tw-96:y=40:fontsize=20:fontcolor=0x9ca7b0,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Shape the camera.':x=96:y=86:fontsize=54:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Move the viewpoint. Refine the aim.':x=98:y=150:fontsize=27:fontcolor=0x9ca7b0,drawbox=x=96:y=194:w=1728:h=1:color=0x29313a:t=fill,drawbox=x=96:y=1008:w=1728:h=1:color=0x29313a:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Live 3D editor / backend wait omitted at this cut':x=96:y=1030:fontsize=20:fontcolor=0x9ca7b0,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "72",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/05_aim.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=7.000000000",
+ "-threads",
+ "2",
+ "-ss",
+ "346.0",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_review.mp4",
+ "-filter_complex",
+ "[1:v]crop=1176:632:380:448,fps=24,trim=end_frame=168,setpts=PTS-STARTPTS,scale=w=1536:h=768:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos:out_color_matrix=bt709,setsar=1[detail];[0:v][detail]overlay=x=(W-w)/2:y=218+(768-h)/2:shortest=1[base];[base]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=96:y=40:fontsize=20:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='03 / TIME':x=w-tw-96:y=40:fontsize=20:fontcolor=0x9ca7b0,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Hold the moment.':x=96:y=86:fontsize=54:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Keep the camera moving.':x=98:y=150:fontsize=27:fontcolor=0x9ca7b0,drawbox=x=96:y=194:w=1728:h=1:color=0x29313a:t=fill,drawbox=x=96:y=1008:w=1728:h=1:color=0x29313a:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Source frame 60 / four camera keys / different output times':x=96:y=1030:fontsize=20:fontcolor=0x9ca7b0,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "168",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/06_time.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=10.125000000",
+ "-threads",
+ "2",
+ "-ss",
+ "0",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/preview_truth.mp4",
+ "-filter_complex",
+ "[1:v]fps=24,trim=end_frame=243,setpts=PTS-STARTPTS,scale=w=1536:h=768:force_original_aspect_ratio=decrease:force_divisible_by=2:flags=lanczos:out_color_matrix=bt709,setsar=1[detail];[0:v][detail]overlay=x=(W-w)/2:y=218+(768-h)/2:shortest=1[base];[base]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=96:y=40:fontsize=20:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='04 / PREVIEW':x=w-tw-96:y=40:fontsize=20:fontcolor=0x9ca7b0,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Preview before you generate.':x=96:y=86:fontsize=54:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='One continuous geometric reference.':x=98:y=150:fontsize=27:fontcolor=0x9ca7b0,drawbox=x=96:y=194:w=1728:h=1:color=0x29313a:t=fill,drawbox=x=96:y=1008:w=1728:h=1:color=0x29313a:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Geometry only / grey marks missing source coverage / not generated video':x=96:y=1030:fontsize=20:fontcolor=0x9ca7b0,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "243",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/07_reference.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-filter_complex_threads",
+ "1",
+ "-f",
+ "lavfi",
+ "-i",
+ "color=c=0x0b0e12:s=1920x1080:r=24:d=3.000000000",
+ "-filter_complex",
+ "[0:v]drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='M E R I D I A N / S T U D I O':x=(w-tw)/2:y=300:fontsize=23:fontcolor=0x9fbfc9,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Compose first. Generate next.':x=(w-tw)/2:y=424:fontsize=82:fontcolor=0xedf0ef,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Meridian Studio / included in the code release':x=(w-tw)/2:y=542:fontsize=32:fontcolor=0x9ca7b0,drawbox=x=925:y=634:w=70:h=2:color=0x9fbfc9:t=fill,drawtext=fontfile='/usr/share/fonts/opentype/urw-base35/NimbusSans-Regular.otf':text='Preview-only walkthrough / final generation not shown':x=(w-tw)/2:y=964:fontsize=21:fontcolor=0x9ca7b0,fade=t=out:st=2.5:d=0.5,format=yuv420p[out]",
+ "-map",
+ "[out]",
+ "-an",
+ "-frames:v",
+ "72",
+ "-c:v",
+ "libx264",
+ "-preset",
+ "medium",
+ "-crf",
+ "18",
+ "-threads",
+ "2",
+ "-color_primaries",
+ "bt709",
+ "-color_trc",
+ "bt709",
+ "-colorspace",
+ "bt709",
+ "-color_range",
+ "tv",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/08_close.mp4"
+ ],
+ [
+ "ffmpeg",
+ "-hide_banner",
+ "-loglevel",
+ "warning",
+ "-n",
+ "-f",
+ "concat",
+ "-safe",
+ "0",
+ "-i",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/edit_concise_01/concat.txt",
+ "-c",
+ "copy",
+ "-movflags",
+ "+faststart",
+ "/home/chenyun/code/minimax-h3/release_recam/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise.mp4"
+ ]
+ ]
+}
diff --git a/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise.mp4 b/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..389c319448847730fa3c4f3699e4ca7482f9dbfe
--- /dev/null
+++ b/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3bf2e235da33464c443754dac8b31d3de92cedda27fd49f38bc898a71050ec7c
+size 18598004
diff --git a/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise_poster.jpg b/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise_poster.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..a688ff693724b3b0988a4e216985e15cb1d8472f
--- /dev/null
+++ b/videos-all/studio_walkthrough/nba3_preview_live_02/studio_walkthrough_concise_poster.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c2b9e52e157c1fa94474e24a25b1d5906df84f1798181f80c856dcea83d8711c
+size 378767
diff --git a/videos-all/teacher_followups/README.md b/videos-all/teacher_followups/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2ce3db6aa62407ea30f243f60bc9dfb8f04e5e0f
--- /dev/null
+++ b/videos-all/teacher_followups/README.md
@@ -0,0 +1,66 @@
+# Meridian / selected times, new perspectives
+
+[Open the synchronized input / teacher viewer](preview.html). This is a review page, not an automatically approved showreel. Original inputs, raw outputs, source clocks and recorded camera controls remain accessible.
+
+## New / one event, an edited sequence
+
+**[Watch the 15.54-second NBA3 intercut](../teaser_meridian_teacher_nba3_edit_v1.mp4).** This follows the editorial approach: source action → generated held view → source action → another held view → two perspectives at the high point → source footage completes the dunk. It does **not** ask a single generation to perform the entire sequence.
+
+Three selected instants: **1.535 s, 2.169 s and 2.836 s** in the original file. Each generated insert uses contiguous output frames 24–95, shown at the original output rate. The final insert presents opposed views together. Source footage and generated views have distinct labels; model inputs, original-file clocks and recorded camera controls are visible. The successful ball/rim contact and landing belong to the **source footage**, not a repaired model result.
+
+The edit uses hard cuts, not a claimed seamless camera transition. No generated-output retiming, frame interpolation, spatial crop or repainting. Source footage uses the previously documented 24-fps conform (~0.970× original-file speed). 373 frames / 24 fps / 1920 × 1080 / silent; 121 source-footage frames, 216 generated-view film frames and 36 title frames. The original clock stays chronological across the inserts. [Exact edit](film_edit_nba3_edit_v1.json) · [Validation and inspection coverage](review/nba3_edit_v1_validation.json).
+
+All eight rendered compositions and the sixteen decoded segment-boundary samples were inspected. Faces, fingers, signage and crowd geometry still vary in generated views. Frame inspection is not a continuous-motion certification. This is a separate local editorial draft; earlier films and raw takes remain unchanged.
+
+## First editorial draft
+
+**New: [ballet v2 / 9.5 seconds](../teaser_meridian_teacher_ballet_v2.mp4)** uses the stronger opposed 24° studies, with disclosed static output crops to reduce distracting stage fixtures. Female output 24–119 uses crop `(520, 0, 1400, 1088)`; male output 24–119 uses `(320, 0, 1120, 1088)`, in **x/y/width/height** coordinates. Uncropped model inputs and recorded camera controls remain visible. [Exact edit](film_edit_ballet_v2.json). All three composition samples were inspected; full decode verifies 228 frames at 24 fps. Fine anatomy changes, a tilted stage floor and a small residual stage-edge reveal remain. Raw takes and v1 are preserved; this is a local candidate, not a fidelity certification.
+
+[Watch the 9.5-second ballet study](../teaser_meridian_teacher_ballet_v1.mp4): two distinct single-image inputs, generated views and recorded camera controls. Both use output 24–119, with no spatial crop or generated-output retiming. [Exact edit](film_edit_ballet_v1.json). The three rendered composition samples were visually checked; full decode confirms 228 frames at 24 fps. This remains a local candidate, not a replacement for the main teaser or continuous visual certification.
+
+The new-view effect is restrained against the dark stage. The female take exposes a bright right-edge lamp; the male take reveals a left-floor light patch. Fine anatomy and cloth are not perfect. [Native/dense inspection coverage](review/first_visual_review.json).
+
+## NBA3: one event
+
+The user-supplied dunk is preserved in full. [Original and preparation](../nba3_teacher30/provenance.json). The first live pilot has a documented ball/net-contact failure; its [full result and review](../nba3_teacher30/README.md) are not hidden or replaced.
+
+The follow-ups deliberately isolate different questions:
+
+| Study | Original file time | Design |
+|---|---:|---|
+| Early flight / plate 38 | 1.534867 s | Held moment, +14° orbit |
+| Ball sweep / plate 54 | 2.168833 s | Held moment, +14° orbit |
+| Raised ball / plate 70 | 2.836167 s | Same held instant, opposed ±14° orbits |
+| Moving pre-contact window | 0–2.902900 s | 73 frames, −8° eased arc, small rise |
+
+All selected source instants were inspected at native scale before generation. The athlete's full silhouette and ball are separate from the rim. Faces, fingers and audience detail are already imperfect in the source. Selected instants are not a repaired full dunk; the shorter moving window is explicitly pre-contact. The held studies share an angular recipe but use different fixed scene pivots, not one identical absolute 3D camera path or automatic subject tracking.
+
+## Ballet: one image
+
+Two native decoded PNGs from distinct shots: female split leap at source frame 2575 / 103.000 s, male side-bend leap at frame 1900 / 76.000 s. Both are **single-image inputs**, not two instants of one jump. [Source, hashes, rights and timing caveats](../overnight/research/dutch_ballet_youtube_source.json).
+
+Several published ballet shots are already nearly held or time-ramped. Their apparent pause must not be credited to Meridian. These pilots test new views from individual images only. Dark studio backgrounds offer limited parallax cues; complete limb anatomy, cloth and lighting need close inspection.
+
+## Reproducibility and acceptance
+
+- Teacher `recam3/full-000200`, no LoRA, `--steps 30 --flow-shift 12`. Default seed 1234; `_s2026` cases use seed 2026 for targeted quality comparisons, not a promised improvement. Each exact recipe is retained. CLI30 corresponds to 29 denoiser forwards. No DMD baseline for these new cases.
+- `export.py` checks exact recorded arguments, finite cameras, full input/output/warp decoding and exact 24-fps PTS; writes dense and native inspection samples. Exporting is not visual inspection.
+- Native canvas preparation is recorded in each study. The review viewer shows uncropped raw output; ballet v2 separately discloses its static editorial crops. No generated-output retiming, interpolation or repainting.
+- The camera plot is recorded conditioning, **not a measurement of generated-camera adherence**. Original PTS describes a published video file, not physical capture time.
+- Local silent research only. Public promotional rights and subject endorsement are not asserted. The main teaser is unchanged until review justifies a better edit.
+
+Run the exporter only for completed outputs; pending jobs are skipped. Existing exported cases are cached, with review decisions read from `selection.json`.
+
+```bash
+/home/chenyun/miniforge3/envs/wan_new/bin/python videos-all/teacher_followups/export.py
+```
+
+## NBA3 / one event, selected times and views
+
+[Watch the 13.54-second NBA3 study](../teaser_meridian_teacher_nba3_v1.mp4). It opens with a moving pre-contact view, selects early-flight instants at 1.535 s and 2.169 s, then shows two opposed views of the same held 2.836 s instant. Model inputs, original-file clocks and recorded camera controls remain visible.
+
+The film is 325 frames at 24 fps, silent, 1920 × 1080. Exact source mappings, controls and selected intervals are in `film_edit_nba3_v1.json`: live output 0..72, held moments 36..95 each, opposed airborne views 24..119, then a 36-frame title. No spatial crop, generated-output retiming or interpolation. All raw takes are preserved. Four example composition frames were visually inspected; this is not a continuous-playback certification.
+
+The held-moment pair is clearer than trying to hide a bad full dunk: faces, hand/ball detail, signage and crowd geometry still vary, and the earlier full-event pilot has a ball/net failure at contact. This film explicitly stops before contact and does not claim that failure was repaired. It is a separate research draft, not a replacement of the main teaser or a public-release clearance.
+
+Further work is targeted: opposed early-flight views, one stronger opposite ballet arc per image, and two independently authored input-time studies. These are not all-camera grids. `export.py` now retains per-frame held states and exports play/hold/resume boundary frames when present.
diff --git a/videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json b/videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json
new file mode 100644
index 0000000000000000000000000000000000000000..a82902394324d2a3d04b781124316886961aaec4
--- /dev/null
+++ b/videos-all/teacher_followups/film_edit_nba3_lora_edit_v2.json
@@ -0,0 +1,1151 @@
+{
+ "output": "teaser_meridian_nba3_lora_edit_v2.mp4",
+ "frames": 373,
+ "fps": 24,
+ "seconds": 15.541666666666666,
+ "crop_format": "x,y,width,height in native output pixels; source-space crops recorded separately",
+ "output_retiming": false,
+ "audio": false,
+ "segments": [
+ {
+ "kind": "original",
+ "start": 0,
+ "frames": 38,
+ "title": [
+ "One event."
+ ],
+ "caption": "The approach / source footage",
+ "detail": "Editorial source / generated intercut. Source action is not a model result. Original-file clock shown; local research draft.",
+ "film_start": 0,
+ "film_end_inclusive": 37,
+ "source_footage": [
+ {
+ "kind": "source_footage",
+ "plate": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "plate_sha256": "5d055116a5081a6a8d07dbd1f285fe99d1591e040dd9d27faee65af548085313",
+ "plate_first": 0,
+ "plate_last": 37,
+ "source_path": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "source_frames": [
+ 0,
+ 1,
+ 2,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 10,
+ 11,
+ 12,
+ 13,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 33,
+ 34,
+ 35,
+ 36,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 44,
+ 45
+ ],
+ "source_seconds": [
+ 0.0,
+ 0.03336666666666667,
+ 0.06673333333333334,
+ 0.13346666666666668,
+ 0.16683333333333333,
+ 0.2002,
+ 0.23356666666666667,
+ 0.26693333333333336,
+ 0.33366666666666667,
+ 0.3670333333333333,
+ 0.4004,
+ 0.4337666666666667,
+ 0.5005,
+ 0.5338666666666667,
+ 0.5672333333333334,
+ 0.6006,
+ 0.6339666666666667,
+ 0.7007,
+ 0.7340666666666666,
+ 0.7674333333333333,
+ 0.8008,
+ 0.8341666666666666,
+ 0.9009,
+ 0.9342666666666667,
+ 0.9676333333333333,
+ 1.001,
+ 1.0343666666666667,
+ 1.1011,
+ 1.1344666666666667,
+ 1.1678333333333333,
+ 1.2012,
+ 1.2679333333333334,
+ 1.3013,
+ 1.3346666666666667,
+ 1.3680333333333334,
+ 1.4014,
+ 1.4681333333333333,
+ 1.5015
+ ],
+ "speed_relative_to_original": 0.9700747967479675,
+ "preparation": "0..149 inclusive mapped onto 124 frames at 24 fps. No spatial crop/resize, interpolation, audio or original modification. Inference applies its normal centered aspect preparation."
+ }
+ ],
+ "selected": []
+ },
+ {
+ "kind": "hero",
+ "takes": [
+ "meridian_nba3_l150_moment38_left14"
+ ],
+ "start": 24,
+ "frames": 72,
+ "title": [
+ "Choose",
+ "a moment."
+ ],
+ "caption": "01 / early flight / change the view, hold the instant",
+ "clock_range": [
+ 0,
+ 4.971633333333333
+ ],
+ "detail": "Generated held view / LoRA150 / CLI4. Selected contiguous output frames 24\u201395; no output retiming or synthetic transition.",
+ "film_start": 38,
+ "film_end_inclusive": 109,
+ "source_footage": [],
+ "selected": [
+ {
+ "name": "meridian_nba3_l150_moment38_left14",
+ "output_first": 24,
+ "output_last": 95,
+ "output_crop": null,
+ "source_frames": [
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46,
+ 46
+ ],
+ "source_seconds": [
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666,
+ 1.5348666666666666
+ ],
+ "input_crop": {
+ "recorded_inference_box": [
+ 7.0,
+ 420.0,
+ 1906.0,
+ 1080.0,
+ 1.0073452256033577
+ ],
+ "canvas": [
+ 1920,
+ 1088
+ ],
+ "editorial_input_crop": null
+ },
+ "source_path": "../nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "clock_scope": "Original nba3.mp4 PTS, uniformly traversed with nearest frames; physical capture speed unknown.",
+ "argv": "--video videos-all/nba3_teacher30/nba3_full_event.mp4 --pivot 0.33,0.46 --pivot-lock --start 38 --freeze 38:124 --yaw 14 --dolly 1.04 --zoom 1 --aim --sweep --ease --frames 124 --canvas 1920x1088 --full 1920 --ckpt /mnt/juicefs-cache/yun/recam_runs/recam3/full-000200 --lora /mnt/juicefs-cache/yun/h3ft/runs/recamdmd/lora-000150 --steps 4 --flow-shift 3 --seed 1234 --model-dir /mnt/juicefs-cache/yun/h3/MiniMax-H3 --out videos-all/meridian_nba3_l150_moment38_left14"
+ }
+ ]
+ },
+ {
+ "kind": "original",
+ "start": 39,
+ "frames": 15,
+ "title": [
+ "Let time",
+ "continue."
+ ],
+ "caption": "The action continues / source footage",
+ "detail": "Editorial source / generated intercut. Source action is not a model result. Original-file clock shown; local research draft.",
+ "film_start": 110,
+ "film_end_inclusive": 124,
+ "source_footage": [
+ {
+ "kind": "source_footage",
+ "plate": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "plate_sha256": "5d055116a5081a6a8d07dbd1f285fe99d1591e040dd9d27faee65af548085313",
+ "plate_first": 39,
+ "plate_last": 53,
+ "source_path": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "source_frames": [
+ 47,
+ 48,
+ 50,
+ 51,
+ 52,
+ 53,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 61,
+ 62,
+ 63,
+ 64
+ ],
+ "source_seconds": [
+ 1.5682333333333334,
+ 1.6016,
+ 1.6683333333333332,
+ 1.7017,
+ 1.7350666666666668,
+ 1.7684333333333333,
+ 1.8351666666666666,
+ 1.8685333333333334,
+ 1.9019,
+ 1.9352666666666667,
+ 1.9686333333333332,
+ 2.0353666666666665,
+ 2.0687333333333333,
+ 2.1021,
+ 2.135466666666667
+ ],
+ "speed_relative_to_original": 0.9700747967479675,
+ "preparation": "0..149 inclusive mapped onto 124 frames at 24 fps. No spatial crop/resize, interpolation, audio or original modification. Inference applies its normal centered aspect preparation."
+ }
+ ],
+ "selected": []
+ },
+ {
+ "kind": "hero",
+ "takes": [
+ "meridian_nba3_l150_moment54_right14"
+ ],
+ "start": 24,
+ "frames": 72,
+ "title": [
+ "See it",
+ "differently."
+ ],
+ "caption": "02 / ball sweep / a different instant and viewpoint",
+ "clock_range": [
+ 0,
+ 4.971633333333333
+ ],
+ "detail": "Generated held view / LoRA150 / CLI4. Selected contiguous output frames 24\u201395; no output retiming or synthetic transition.",
+ "film_start": 125,
+ "film_end_inclusive": 196,
+ "source_footage": [],
+ "selected": [
+ {
+ "name": "meridian_nba3_l150_moment54_right14",
+ "output_first": 24,
+ "output_last": 95,
+ "output_crop": null,
+ "source_frames": [
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65,
+ 65
+ ],
+ "source_seconds": [
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333,
+ 2.168833333333333
+ ],
+ "input_crop": {
+ "recorded_inference_box": [
+ 7.0,
+ 420.0,
+ 1906.0,
+ 1080.0,
+ 1.0073452256033577
+ ],
+ "canvas": [
+ 1920,
+ 1088
+ ],
+ "editorial_input_crop": null
+ },
+ "source_path": "../nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "clock_scope": "Original nba3.mp4 PTS, uniformly traversed with nearest frames; physical capture speed unknown.",
+ "argv": "--video videos-all/nba3_teacher30/nba3_full_event.mp4 --pivot 0.35,0.43 --pivot-lock --start 54 --freeze 54:124 --yaw -14 --dolly 1.04 --zoom 1 --aim --sweep --ease --frames 124 --canvas 1920x1088 --full 1920 --ckpt /mnt/juicefs-cache/yun/recam_runs/recam3/full-000200 --lora /mnt/juicefs-cache/yun/h3ft/runs/recamdmd/lora-000150 --steps 4 --flow-shift 3 --seed 1234 --model-dir /mnt/juicefs-cache/yun/h3/MiniMax-H3 --out videos-all/meridian_nba3_l150_moment54_right14"
+ }
+ ]
+ },
+ {
+ "kind": "original",
+ "start": 55,
+ "frames": 15,
+ "title": [
+ "Move to",
+ "the next."
+ ],
+ "caption": "Toward the high point / source footage",
+ "detail": "Editorial source / generated intercut. Source action is not a model result. Original-file clock shown; local research draft.",
+ "film_start": 197,
+ "film_end_inclusive": 211,
+ "source_footage": [
+ {
+ "kind": "source_footage",
+ "plate": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "plate_sha256": "5d055116a5081a6a8d07dbd1f285fe99d1591e040dd9d27faee65af548085313",
+ "plate_first": 55,
+ "plate_last": 69,
+ "source_path": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "source_frames": [
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 73,
+ 74,
+ 75,
+ 76,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 84
+ ],
+ "source_seconds": [
+ 2.2355666666666667,
+ 2.2689333333333335,
+ 2.3023,
+ 2.3356666666666666,
+ 2.3690333333333333,
+ 2.435766666666667,
+ 2.469133333333333,
+ 2.5025,
+ 2.5358666666666667,
+ 2.6026,
+ 2.6359666666666666,
+ 2.6693333333333333,
+ 2.7027,
+ 2.736066666666667,
+ 2.8028
+ ],
+ "speed_relative_to_original": 0.9700747967479675,
+ "preparation": "0..149 inclusive mapped onto 124 frames at 24 fps. No spatial crop/resize, interpolation, audio or original modification. Inference applies its normal centered aspect preparation."
+ }
+ ],
+ "selected": []
+ },
+ {
+ "kind": "pair",
+ "takes": [
+ "meridian_nba3_l150_air_left14",
+ "meridian_nba3_l150_air_right14"
+ ],
+ "start": 24,
+ "frames": 72,
+ "title": [
+ "One instant. Two perspectives."
+ ],
+ "labels": [
+ "GENERATED VIEW / LEFT ARC",
+ "GENERATED VIEW / RIGHT ARC"
+ ],
+ "caption": "03 / the same held 2.836 s instant, two opposed camera controls",
+ "clock_range": [
+ 0,
+ 4.971633333333333
+ ],
+ "shared_camera_scale": true,
+ "detail": "Two independently generated views of the same input instant. Recorded controls, not verified multi-view geometry.",
+ "film_start": 212,
+ "film_end_inclusive": 283,
+ "source_footage": [],
+ "selected": [
+ {
+ "name": "meridian_nba3_l150_air_left14",
+ "output_first": 24,
+ "output_last": 95,
+ "output_crop": null,
+ "source_frames": [
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85
+ ],
+ "source_seconds": [
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667
+ ],
+ "input_crop": {
+ "recorded_inference_box": [
+ 7.0,
+ 420.0,
+ 1906.0,
+ 1080.0,
+ 1.0073452256033577
+ ],
+ "canvas": [
+ 1920,
+ 1088
+ ],
+ "editorial_input_crop": null
+ },
+ "source_path": "../nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "clock_scope": "Original nba3.mp4 PTS, uniformly traversed with nearest frames; physical capture speed unknown.",
+ "argv": "--video videos-all/nba3_teacher30/nba3_full_event.mp4 --pivot 0.375,0.48 --pivot-lock --start 70 --freeze 70:124 --yaw 14 --dolly 1.04 --zoom 1 --aim --sweep --ease --frames 124 --canvas 1920x1088 --full 1920 --ckpt /mnt/juicefs-cache/yun/recam_runs/recam3/full-000200 --lora /mnt/juicefs-cache/yun/h3ft/runs/recamdmd/lora-000150 --steps 4 --flow-shift 3 --seed 1234 --model-dir /mnt/juicefs-cache/yun/h3/MiniMax-H3 --out videos-all/meridian_nba3_l150_air_left14"
+ },
+ {
+ "name": "meridian_nba3_l150_air_right14",
+ "output_first": 24,
+ "output_last": 95,
+ "output_crop": null,
+ "source_frames": [
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85,
+ 85
+ ],
+ "source_seconds": [
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667,
+ 2.8361666666666667
+ ],
+ "input_crop": {
+ "recorded_inference_box": [
+ 7.0,
+ 420.0,
+ 1906.0,
+ 1080.0,
+ 1.0073452256033577
+ ],
+ "canvas": [
+ 1920,
+ 1088
+ ],
+ "editorial_input_crop": null
+ },
+ "source_path": "../nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "clock_scope": "Original nba3.mp4 PTS, uniformly traversed with nearest frames; physical capture speed unknown.",
+ "argv": "--video videos-all/nba3_teacher30/nba3_full_event.mp4 --pivot 0.375,0.48 --pivot-lock --start 70 --freeze 70:124 --yaw -14 --dolly 1.04 --zoom 1 --aim --sweep --ease --frames 124 --canvas 1920x1088 --full 1920 --ckpt /mnt/juicefs-cache/yun/recam_runs/recam3/full-000200 --lora /mnt/juicefs-cache/yun/h3ft/runs/recamdmd/lora-000150 --steps 4 --flow-shift 3 --seed 1234 --model-dir /mnt/juicefs-cache/yun/h3/MiniMax-H3 --out videos-all/meridian_nba3_l150_air_right14"
+ }
+ ]
+ },
+ {
+ "kind": "original",
+ "start": 71,
+ "frames": 53,
+ "title": [
+ "Back to",
+ "the event."
+ ],
+ "caption": "The dunk completes in the original footage / not a generated result",
+ "detail": "Editorial source / generated intercut. Source action is not a model result. Original-file clock shown; local research draft.",
+ "film_start": 284,
+ "film_end_inclusive": 336,
+ "source_footage": [
+ {
+ "kind": "source_footage",
+ "plate": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_full_event.mp4",
+ "plate_sha256": "5d055116a5081a6a8d07dbd1f285fe99d1591e040dd9d27faee65af548085313",
+ "plate_first": 71,
+ "plate_last": 123,
+ "source_path": "/home/chenyun/code/minimax-h3/release_recam/videos-all/nba3_teacher30/nba3_original.mp4",
+ "source_sha256": "fd651ac29ceecc75b8f2a7821baf95081055387a9d71b69dd175ac53b5f42f1a",
+ "source_frames": [
+ 86,
+ 87,
+ 88,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 96,
+ 97,
+ 98,
+ 99,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 113,
+ 114,
+ 115,
+ 116,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 124,
+ 125,
+ 126,
+ 127,
+ 128,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 136,
+ 137,
+ 138,
+ 139,
+ 141,
+ 142,
+ 143,
+ 144,
+ 145,
+ 147,
+ 148,
+ 149
+ ],
+ "source_seconds": [
+ 2.8695333333333335,
+ 2.9029,
+ 2.9362666666666666,
+ 3.003,
+ 3.036366666666667,
+ 3.069733333333333,
+ 3.1031,
+ 3.1364666666666667,
+ 3.2032,
+ 3.2365666666666666,
+ 3.2699333333333334,
+ 3.3033,
+ 3.370033333333333,
+ 3.4034,
+ 3.4367666666666667,
+ 3.4701333333333335,
+ 3.5035,
+ 3.5702333333333334,
+ 3.6036,
+ 3.6369666666666665,
+ 3.6703333333333332,
+ 3.7037,
+ 3.7704333333333335,
+ 3.8038,
+ 3.8371666666666666,
+ 3.8705333333333334,
+ 3.9372666666666665,
+ 3.9706333333333332,
+ 4.004,
+ 4.037366666666666,
+ 4.070733333333333,
+ 4.137466666666667,
+ 4.170833333333333,
+ 4.2042,
+ 4.237566666666667,
+ 4.270933333333334,
+ 4.337666666666666,
+ 4.371033333333333,
+ 4.4044,
+ 4.437766666666667,
+ 4.471133333333333,
+ 4.537866666666667,
+ 4.571233333333334,
+ 4.6046,
+ 4.637966666666666,
+ 4.7047,
+ 4.738066666666667,
+ 4.771433333333333,
+ 4.8048,
+ 4.838166666666667,
+ 4.9049,
+ 4.938266666666666,
+ 4.971633333333333
+ ],
+ "speed_relative_to_original": 0.9700747967479675,
+ "preparation": "0..149 inclusive mapped onto 124 frames at 24 fps. No spatial crop/resize, interpolation, audio or original modification. Inference applies its normal centered aspect preparation."
+ }
+ ],
+ "selected": []
+ },
+ {
+ "kind": "brand",
+ "frames": 36,
+ "title": [
+ "meridian"
+ ],
+ "caption": "A new perspective on space and time.",
+ "detail": "One event. Anywhere. Anytime.",
+ "film_start": 337,
+ "film_end_inclusive": 372,
+ "source_footage": [],
+ "selected": []
+ }
+ ]
+}
diff --git a/videos-all/teaser_meridian_compound_motor_dust_explained_v1.mp4 b/videos-all/teaser_meridian_compound_motor_dust_explained_v1.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..4c68eb3a76a4cb66e6fec5a63470e245a9c3510d
--- /dev/null
+++ b/videos-all/teaser_meridian_compound_motor_dust_explained_v1.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3b286a819ac1ae48a634bb52932f49b0b28741529a0c4ada9c709881489beb24
+size 10845186
diff --git a/videos-all/teaser_meridian_showcase_v12.mp4 b/videos-all/teaser_meridian_showcase_v12.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..e1f77bff6ccc6e446c2496d1ba89f9e3f3982a54
--- /dev/null
+++ b/videos-all/teaser_meridian_showcase_v12.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9fd39f08d477bd1ec97020308ac6a0749f44f54d1f6ce12e6c64881bbeafd094
+size 36374764
diff --git a/videos-all/teaser_meridian_showcase_v7.mp4 b/videos-all/teaser_meridian_showcase_v7.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..28e6fdb4ca2d0d4423f2ef2797a4d521495eabeb
--- /dev/null
+++ b/videos-all/teaser_meridian_showcase_v7.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5ecdc6a8b86132313eff9455c6217a9428ae49fa7e1685b56f1f832ef00ed14d
+size 36223963
diff --git a/videos-all/teaser_meridian_showcase_v9.mp4 b/videos-all/teaser_meridian_showcase_v9.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..fde90d4898c2d75dd54e8b8825b26807274e2d35
--- /dev/null
+++ b/videos-all/teaser_meridian_showcase_v9.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6dbd3b4b7dbb3dfd97dbdc5596897b579f3af226c200e97b3dc50398c4f1e61c
+size 36250001
diff --git a/videos-all/va_pi3_hi/out.mp4 b/videos-all/va_pi3_hi/out.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..706ea024536361832dbb8132021df4848490e181
--- /dev/null
+++ b/videos-all/va_pi3_hi/out.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b969232c38d149ecc880513eb8b291bbf8d428bc5ff916492d426a0dc0348238
+size 1592352
diff --git a/videos-all/va_pi3_hi/source.mp4 b/videos-all/va_pi3_hi/source.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..5cbea91fefb614b17b980249011767fc06c1fdb8
--- /dev/null
+++ b/videos-all/va_pi3_hi/source.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ae4257c88de563e6ccbba39ef13f03ecb6079d5814a758da0cc7e5863f2bc5ab
+size 1754720