Project and Core Concepts
Project
In every call that involves building an asset (rendering the output video, generating video, image, voice, etc), project is a required parameter.
Somewhere at the top of your script, you should initialize Project, like this:
from pathlib import Path
from imaginaryarts import Project
ROOT = Path(__file__).parent
video_id = "my_first_vid"
project = Project(id=video_id, workdir=ROOT / video_id, api_key=...)Project __init__ API:
| param | type | explanation |
|---|---|---|
| id | string | Used for caching. Always use the same ID for the same project. |
| workdir | Path | This is the path to the folder where everything that gets build in the process of creating a video gets saved. If you keep the same workdir, your assets will be cached, and you won't have to regenerate assets every time. |
| api_key | string | Your Imaginary Arts API key. Passed in to project because project itself needs to be passed in to every call involving any kind of generation, so you don't need to pass in api_key more than once. See more about API key in the Pricing section. |
Caching
A folder will be created at the location you specify in the workdir parameter to Project, and that folder will have the following example contents:
explainer_video
assets
3d98ab1cca24_1.wav
harbour_d5b7a775a6e5_1.mp4
harbour_93849d7dc2e4_1.json
inhale_dd71f54db3f8_1.mp4
inhale_464110d33267_1.json
output
explainer_video.mp4
explainer_video_2.mp4Output
The output folder is, naturally, where the output gets saved. The final rendered video. If you regenerate several times, it will just increment (_2, _3, etc..)
Assets
Everything that is computed/generated and costs money (i.e. API calls to AI services) is saved in the assets folder. The next time you run the same script that produced these assets (without changing any inputs), it will re-use the same assets, thereby saving you money and keeping the video consistent unless you want to change something.
The long strange string of text (e.g. d5b7a775a6e5) in the file names here is a hash. A hashing function takes a set of inputs and turns it into a random string of characters. The same inputs always produce the same string of characters.
Every function that produces an asset, such as e.g. create_voiceover below:
voiceover = create_voiceover(
"The narrator speaks these words.",
voice=Voices.AmericanExplainer,
project=project
)..produces a hash from its inputs and checks if an asset with that hash already exists in the assets folder. If it does exist, it just uses that existing file; and if it doesn't exist, it runs the function and produces a new asset.
So if you change the inputs to the create_voiceover function in any way (e.g. Voices.AmericanExplainer -> Voices.BritishExplainer; or "The narrator speaks these words." -> "The narrator speaks the following words."), it will regenerate.
Bottom Line: The library will cache as much as possible/regenerate as infrequently as possible (because regenerating costs money).
If you explicitly want to regenerate an asset with exactly the same input (as might be the case with image and video generation, where there is a degree of randomness, and sometimes a video comes out better after a few takes), you use take=2, take=3, etc. If you want to go back to a previous take, just change the take parameter to a previous number — that generation will still be cached in the assets folder.
Naming cached files
Every function that generates something also accepts a name. It is a label for the files in the assets folder, so harbour_d5b7a775a6e5_1.mp4 is easier to find than d5b7a775a6e5_1.mp4. The name is not part of the hash: renaming something renames its files instead of regenerating them.
Time is in milliseconds
Every time in the library is an integer number of milliseconds. 5000 is five seconds. That goes for intervals such as interval=[0, 5000], for at=, for the timestamps on words, for trims, and for durations. There are no seconds anywhere in the public API, so there is never a question of which unit a number is in.