DEV Community

Amitesh
Amitesh

Posted on

Building a Fully Automated Asset Generation AI Pipeline

What if a racing game didn't need a developer to manually prepare its next challenge?

Instead of creating a track, selecting an environment, composing a soundtrack, exporting assets, uploading files, and publishing a new build every week, the entire process could run as an automated content pipeline.

That was the idea behind Weekly Race Generator: a system that creates and publishes a new playable racing challenge on a recurring schedule.

The important distinction is that the racing track itself is procedurally generated, while the surrounding creative assets—skybox, music, artwork, and loading screen—are generated using AI.

The result is a pipeline that combines deterministic procedural generation with generative AI and cloud infrastructure.


The idea

A weekly racing challenge consists of several pieces:

  • A procedurally generated racing track
  • An AI-generated skybox/environment
  • AI-generated background music
  • AI-generated promotional artwork
  • A loading screen derived from the generated environment
  • Metadata describing the competition
  • All of the assets required by the game

The goal was to make these pieces come together automatically.

Once the system is running, the intended workflow looks roughly like this:

The interesting part isn't any individual generator. It is connecting all of them into a reliable pipeline.


How the system works

1. A competition is the unit of generation

The system treats each weekly challenge as a competition with an identifier such as:

s1-w22
Enter fullscreen mode Exit fullscreen mode

The current competition is stored in a current.json object.

This became important because the generator should not depend on an environment variable to determine which week comes next.

Instead, the pipeline:

  1. Reads the current competition.
  2. Determines the next competition.
  3. Generates the new challenge.
  4. Publishes it.
  5. Updates the current competition only after successful generation.

This makes the competition state part of the generated content rather than deployment configuration.

It also means that invoking the generator again naturally advances the competition.


2. Procedural track generation

The track is deliberately not AI-generated.

The geometry is generated algorithmically according to the rules of the racing game.

This provides something that generative image models aren't particularly good at guaranteeing: a track that is actually usable by the game.

A procedural generator can enforce constraints such as:

  • Track continuity
  • Closed-loop topology
  • Start/finish placement
  • Appropriate curvature
  • Track length
  • Driving direction
  • Valid checkpoints
  • Game-specific gameplay requirements

The output is therefore deterministic in structure even though the resulting layout can vary from one competition to another.

This separation of responsibilities is useful:

Algorithms guarantee gameplay; generative AI provides atmosphere and creative variation.


3. Generating the world around the track

Once the track theme is established, the system generates the visual environment.

The skybox is produced using a generative image model.

For example, a futuristic city theme might produce an environment containing elevated highways, towers, neon lighting and atmospheric effects.

The generated skybox then becomes an input to another stage of the pipeline.

This was an important design decision.

Initially, the loading screen and skybox were generated independently. Even when both were generated from the same textual theme, they could look like two completely different worlds.

The solution was to make the generated skybox the visual source of truth.

                 Theme
                   │
                   ▼
              Skybox AI
                   │
                   ▼
            Generated Skybox
                   │
                   ├──────────────► Game environment
                   │
                   ▼
          Image-to-image generation
                   │
                   ▼
             Loading Screen
Enter fullscreen mode Exit fullscreen mode

The loading screen is therefore treated as a cinematic crop of the same generated world rather than a separate interpretation of the theme.

This produces much stronger visual consistency.


4. Music generation

The visual assets aren't the only generative component.

Each competition also gets its own music.

The music generation stage uses Google's generative music capabilities through the Genblaze integration.

The generator produces a soundtrack based on the theme and desired mood of the competition.

This means that a weekly challenge can have its own combination of:

Track layout + environment + soundtrack + artwork

without requiring a human to manually assemble those assets every week.


5. Genblaze as the generation layer

The Python application uses the Genblaze SDK as the foundation for interacting with the generative media providers.

Rather than writing the entire application around one particular provider implementation, the project keeps generation behind application-level interfaces.

Conceptually:

Competition Builder
        │
        ├── Track Generator
        ├── Skybox Generator
        ├── Music Generator
        ├── Artwork Generator
        └── Loading Screen Generator
                │
                ▼
           Genblaze / Providers
Enter fullscreen mode Exit fullscreen mode

This separation makes the pipeline easier to evolve.

For example, changing how a particular asset is generated does not need to change the competition orchestration itself.

The application is responsible for deciding what needs to be generated.

The provider integrations are responsible for deciding how it is generated.


6. Backblaze B2 as the content store

Once generation is complete, the resulting assets need somewhere to live.

That's where Backblaze B2 Cloud Storage comes in.

The generated challenge is packaged with its assets and uploaded to B2.

The storage hierarchy effectively becomes the content distribution layer for the game.

A simplified representation looks like:

B2
└── competitions/
    ├── s1-w21/
    │   ├── current.json
    │   ├── manifest.json
    │   ├── skybox.png
    │   ├── loading.png
    │   ├── artwork.png
    │   ├── music.wav
    │   └── track...
    │
    └── s1-w22/
        └── ...
Enter fullscreen mode Exit fullscreen mode

The important architectural decision here is that B2 becomes the source of truth for published content.

The generator doesn't need to remain available after a challenge has been published.

The game only needs to retrieve the published challenge.


7. Temporary files and cleanup

One surprisingly important part of the system was temporary file management.

Some generation operations naturally produce files locally before they can be uploaded.

That works differently in a serverless environment.

AWS Lambda provides a writable temporary filesystem through /tmp, while the deployed application itself is effectively read-only.

The application therefore uses a dedicated temporary directory during generation:

/tmp/scr-weekly-assets/
Enter fullscreen mode Exit fullscreen mode

The lifecycle is:

Generate
   │
   ▼
Write temporary asset
   │
   ▼
Upload to B2
   │
   ▼
Delete local asset
Enter fullscreen mode Exit fullscreen mode

Cleanup is part of the successful generation lifecycle rather than an optional housekeeping operation.

After a successful run, the temporary generation directory should contain no leftover assets.

This became particularly important before moving the application into Lambda because a locally working application can accidentally depend on filesystem behavior that doesn't exist in a serverless environment.


8. Running the generator on AWS Lambda

The generator is packaged as a Python AWS Lambda function.

The Lambda entry point is intentionally thin:

Lambda handler
      │
      ▼
build_default_app()
      │
      ▼
CompetitionApp.run()
      │
      ▼
CompetitionBuilder
Enter fullscreen mode Exit fullscreen mode

The generation logic does not live inside the Lambda handler.

This keeps the application executable in two ways:

Local CLI ───────┐
                ├──► CompetitionApp
Lambda handler ─┘
Enter fullscreen mode Exit fullscreen mode

The same application code can therefore be tested locally and executed by Lambda.

This was useful during development because I could run the generator locally while developing the pipeline, then deploy essentially the same execution path to AWS.


9. Making Python dependencies Lambda-compatible

One of the more interesting problems appeared only after deploying the application.

The initial Lambda invocation failed with:

No module named 'pydantic_core._pydantic_core'
Enter fullscreen mode Exit fullscreen mode

The Python package was present, but one of its native components had been built for the wrong platform.

This is an easy problem to encounter when building Lambda deployment packages on macOS.

My local machine was:

macOS
Python 3.11
Enter fullscreen mode Exit fullscreen mode

while Lambda runs on AWS's Linux environment.

Python dependencies containing native extensions therefore cannot always simply be copied from the local virtual environment.

The deployment package needs dependencies built for the environment Lambda actually uses.

This is one of those issues that isn't obvious from the application's Python code itself.

Everything can work perfectly locally and still fail immediately in Lambda because the binary dependencies target a different operating system or architecture.


10. EventBridge turns the generator into an autonomous system

With the generator working as a Lambda function, the final piece is scheduling.

AWS EventBridge Scheduler invokes the Lambda periodically.

The resulting architecture is:

                EventBridge
                    │
             scheduled trigger
                    │
                    ▼
             AWS Lambda
                    │
                    ▼
         Weekly Race Generator
                    │
          ┌─────────┴─────────┐
          ▼                   ▼
    Generative AI          Procedural
      providers             systems
          │                   │
          └─────────┬─────────┘
                    ▼
               B2 Storage
                    │
                    ▼
                Game
Enter fullscreen mode Exit fullscreen mode

The generator no longer needs a human to start it.

A scheduled event starts the process, the application determines the next competition, generates the content, publishes it to B2, and updates the competition state.

That is what turns a collection of generators into an autonomous content pipeline.


Reliability matters more than generation

Generating an image or a piece of music is relatively straightforward.

The harder problem is making the entire operation reliable.

A weekly generation job needs to answer questions such as:

  • What happens if an AI request fails?
  • What happens if an asset uploads successfully but cleanup fails?
  • What happens if the Lambda invocation is interrupted?
  • When should the competition number advance?
  • What happens if the same job is invoked twice?
  • Where is the published version of the challenge?
  • How can I determine what happened after the job finishes?

These questions shaped the architecture more than the individual generation APIs did.

The application has explicit configuration validation, structured logging, temporary-file cleanup and a clear publishing lifecycle.

AWS CloudWatch provides the execution logs, making it possible to inspect a generation run after the fact.


The complete pipeline

Putting everything together:

                    EventBridge
                        │
                        │ schedule
                        ▼
                  AWS Lambda
                        │
                        ▼
              Read current.json
                        │
                        ▼
             Determine next week
                        │
          ┌─────────────┼─────────────┐
          │             │             │
          ▼             ▼             ▼
     Procedural      Skybox AI     Music AI
       Track            │
          │             │
          │             ▼
          │       Loading Screen
          │        Image-to-Image
          │             │
          └──────┬──────┴──────┐
                 ▼             ▼
             Artwork       Challenge
                 │          Metadata
                 └──────┬──────┘
                        ▼
                   Upload to B2
                        │
                        ▼
                 Publish challenge
                        │
                        ▼
                 Update current.json
                        │
                        ▼
                   Cleanup /tmp
Enter fullscreen mode Exit fullscreen mode

The game doesn't need to know how any of this happened.

It simply consumes the latest published challenge.


What I found most interesting

The most interesting part of this project wasn't generating the individual assets.

It was discovering how different technologies complement each other.

Procedural generation is good at producing structured, rule-constrained content.

Generative AI is good at producing creative, visual and musical content.

Genblaze provides an abstraction layer for connecting the application to generative providers.

AWS Lambda provides an execution environment without needing a continuously running server.

EventBridge provides the recurring trigger.

Backblaze B2 provides persistent storage for the generated content.

Together, they form something that is more interesting than any one component:

A system that can continuously create new game content without requiring a developer to manually assemble and publish every update.


What's next

The natural extension is to make the generation pipeline increasingly autonomous.

For example, future versions could use gameplay telemetry to influence generation:

Player telemetry
      │
      ▼
Difficulty analysis
      │
      ▼
Generation parameters
      │
      ▼
New procedural track
      │
      ├──► New environment
      ├──► New music
      └──► New artwork
              │
              ▼
          Next challenge
Enter fullscreen mode Exit fullscreen mode

Instead of simply generating a new challenge every week, the system could learn what makes a challenge interesting and adapt future challenges accordingly.

That would turn a scheduled content generator into a feedback-driven content system.


Conclusion

Weekly Race Generator started with a relatively simple question:

Could a racing game continuously produce new content without someone manually building each week's challenge?

The answer is yes—but the interesting engineering challenge is not simply calling generative AI APIs.

It is building the infrastructure around them.

By combining procedural game-content generation, generative media, Genblaze, AWS Lambda, EventBridge and Backblaze B2, it is possible to build a pipeline where the creation and publication of new game content becomes an automated operation rather than a recurring manual task.

The broader idea extends well beyond racing games.

The same architecture could be used for games that need continuously changing environments, levels, quests, artwork, music or other forms of generated content.

The game becomes the consumer of a content pipeline that can keep creating new experiences on its own.

Top comments (0)