Dalian Works
aifilm

Five Pitfalls to Avoid: From Idempotent Locks to CRTOR Binding for Smoother AI Film Production

Published 2026-11-02 · Translated from the Chinese original

The first pitfall is that atctoscene has an idempotent lock and cannot be rerun.

The symptom is clear: when you call funx.atctoscene a second time on the same dbvideo_article record, the system throws an error stating that the article has already been processed and refuses to execute.

The error message may contain keywords like "key duplicate" or "already processed," depending on the database driver you use.

The root cause is that atctoscene writes a processing lock onto the article record each time it runs. The lock key is generated from the combination of bookcode and articlecode, marking that the storyboard generation for that article is complete.

This design is intended to prevent the same chapter from being split into two different storyboard sets by concurrent processes on multiple machines, which would cause duplicate data in the dbvideo_process table.

But it also creates a problem: if you modify the original excerpt or want to re-split shots, you cannot simply call it again—you must first manually unlock it.

The solution is not complicated. Locate the corresponding record in the dbvideo_article table, clear the value of the atctoscene lock field—typically setting the process_lock field to 0 or deleting the lock_time timestamp—and then call it again.

However, note that unlocking and re-executing atctoscene does not automatically delete existing process records; the old shots will duplicate the newly generated ones.

So the correct approach is to manually delete all dbvideo_process records associated with that articlecode first, while retaining existing roles and places in dbvideo_roles and dbvideo_places—because re-splitting will write the same roles and places again, but does the roles and places table allow duplicate rows?

The answer is no. So before deleting processes, you must check whether roles and places already contain identical names; if so, reuse their rolecode and placecode rather than inserting new rows.

In short: after unlocking, clean up processes first, then reuse existing roles and places, and finally execute atctoscene. This is the safest sequence.

The second pitfall is that the large-model channel binds uid to CRTOR.

The symptom is that when you submit drawrole or placeaiwords requests simultaneously across multiple machines or multiple threads, some requests return authentication failures or errors indicating the model configuration does not exist—yet the same batch of requests runs fine on another machine.

BODY:

The root cause is that within dbroutine's channel scheduler, each uid is bound to a set of large-model channel configurations, including the requested model version, sampling parameters, style presets, and the corresponding API keys.

If the CRTOR carried by your task submission does not match the uid configured in the current environment, the system cannot find the corresponding channel configuration and throws an error.

A more practical scenario: you use uid_A on one machine to generate character images for the first two hundred shots, then switch to another machine to generate the next two hundred, but the second machine's configuration file has uid_B. All the source paths for character images generated by uid_A still exist, yet the new image generation requests carry uid_B. For the same book, imgstyle may map to different model weights under different uids, causing subsequent images to be stylistically inconsistent with earlier ones—or even failing outright.

The solution is to set the same CRTOR value across all machines, or check before task startup whether the current environment's uid matches the CRTOR field in the project record.

You can store a crtor field in dbvideo_bookidx and read it each time a worker starts; if it does not match, automatically switch the environment variable.

Ensure that all drawrole calls for characters and all placeaiwords calls for locations throughout the entire book consistently use the same uid, so channel configurations remain continuous and stable.

The third pitfall is that places is not a location dictionary—it is one row per shot.

The symptom: when you try to query all distinct location names from dbvideo_places to generate a location list, you get a large number of duplicate rows—the same location, such as the foot of Cangwu Mountain, appears dozens of times.

You might assume this is data redundancy, but it is actually the intended design.

Each row in the dbvideo_places table represents one occurrence of a location within a single shot, not a primary data dictionary entry.

Each row has its own placecode, placename, environment description field, and corresponding imgstyle. Even when names are identical, the environment descriptions for different shots may differ slightly due to context—for instance, the foot of Cangwu Mountain in the rain versus on a clear day are two different environment descriptions.

If you treat it as a dictionary and deduplicate it, you lose the unique environmental information tied to each shot.

The fix is to clearly distinguish the two concepts when writing requirements: when you need a location list, use `SELECT DISTINCT placename FROM dbvideo_places`;

BODY:

To get the location instance for a specific shot, use `SELECT * FROM dbvideo_places WHERE placecode = specific_value`.

Never use DISTINCT as a blanket replacement for the whole table; otherwise, when generating scene composite images later, the correct environment text will not be referenced.

In practice, if you mistakenly delete duplicate location rows, some process records will have foreign key failures, because the placecode in the process table points to those deleted rows, resulting in orphan records.

The correct approach is to keep all rows and only deduplicate at query time.

The fourth pitfall is that first and last frames must be generated as a pair.

The symptom: during the video generation stage, the Jimeng API returns an error code indicating missing frames, or the generated video appears as a black screen, because the system cannot find the last frame path.

The root cause: when arcpictask generates images, if the first frame succeeds but the last frame times out or fails, the system writes the STCODE.png placeholder into the secondpic field.

This placeholder is not a real image—it is an empty file name. When the video generator attempts to read that file, it only gets a file-not-found error.

Fix steps, step one: first query firstpic and secondpic for that shot in dbvideo_process, and confirm whether the secondpic field value is STCODE.png.

If it is, delete both existing rows for that shot directly—do not delete only one row, because the first and last frames must maintain the same task ID context.

Step two: re-call arcpictask with the exact same prompt and source image paths as before, ensuring the newly generated first and last frames maintain consistent composition.

Step three: after regeneration completes, immediately verify that both files exist and have non-zero file sizes, using a filesystem command to count bytes.

Step four: update the process table status to ready.

This workflow must be carried out consistently in every batch of tasks. If you run multiple groups of arcpictask in batches, check each batch after it finishes—do not wait until all batches are complete, otherwise intermediate errors will accumulate and make troubleshooting much harder.

The fifth pitfall is that vdurl is completely empty.

The symptom: the vdurl field in all shot records across the entire book is NULL, yet playing the finished film shows no issues whatsoever.

The root cause: video files exist only in Jimeng's cloud service. The local database does not store video addresses—only task IDs.

If you try to use the vdurl field to confirm whether video generation is complete, you will draw the wrong conclusion.

BODY:

The solution is to rely on the taskid field instead and proactively query the task status through Jimeng's query endpoint.

Three alternative verification methods: first, check that taskid is non-empty, which indicates the task was successfully created;

second, call Jimeng's query endpoint and parse the returned status value—if it is success, generation is complete; if it is failed, you need to rerun;

third, randomly sample three shots, obtain valid playback links from Jimeng, use a tool to download them, and perform a rough file size check—calculate whether the file size is greater than the product of that shot's duration and bitrate.

In practice, it is recommended that after each batch of video generation completes, you write taskid into the process table and periodically use a script to scan for records where taskid is empty or queries fail.

Once you stop depending on the vdurl field, you will get used to managing video generation tasks through taskid and external interface feedback. Once this habit is established, other links that rely on external services can be troubleshot with a similar approach.

The five pitfalls above cover five critical links in sequence: storyboard generation, model channels, location data, paired image generation, and video storage. Each one will surface during actual operation. Following the operational steps described here can save you from most redundant work.