Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/backend/backend/blocks/ai_shortform_video_block.py (Python)

Code before:
    def voice_id(self):
        voice_id_map = {
            Voice.LILY: "pFZP5JQG7iQjIQuC4Bku",
            Voice.DANIEL: "onwK4e9ZLuTAKqWW03F9",
            Voice.BRIAN: "nPczCjzI2devNBz1zQrb",
            Voice.JESSICA: "cgSgspJ2msm6clMCkdW9",
            Voice.CHARLOTTE: "XB0fDUnXU5powFXDhCwa",
            Voice.CALLUM: "N2lVS1w4EtoT3dr4eOWO",
            Voice.EVA: "FGY2WhTYpPnrIDTdsKH5",
        }
        return voice_id_map[self]

    def __str__(self):
        return self.value


class VisualMediaType(str, Enum):
    STOCK_VIDEOS = ("stockVideo",)
    MOVING_AI_IMAGES = ("movingImage",)
    AI_VIDEO = ("aiVideo",)


logger = logging.getLogger(__name__)


class _RevidMixin:
    """Utility mix‑in that bundles the shared webhook / polling helpers."""

    def create_webhook(self):
        url = "https://webhook.site/token"
        headers = {"Accept": "application/json", "Content-Type": "application/json"}
        response = requests.post(url, headers=headers)
        webhook_data = response.json()
        return webhook_data["uuid"], f"https://webhook.site/{webhook_data['uuid']}"

    def create_video(self, api_key: SecretStr, payload: dict) -> dict:
        url = "https://www.revid.ai/api/public/v2/render"
        headers = {"key": api_key.get_secret_value()}
        response = requests.post(url, json=payload, headers=headers)
        logger.debug(
            f"API Response Status Code: {response.status_code}, Content: {response.text}"
        )
        return response.json()

    def check_video_status(self, api_key: SecretStr, pid: str) -> dict:
        url = f"https://www.revid.ai/api/public/v2/status?pid={pid}"
        headers = {"key": api_key.get_secret_value()}
        response = requests.get(url, headers=headers)
        return response.json()

    def wait_for_video(

Review comment (refactor):
Most block sets that have shared API logic use module-level helper functions or an `_api` submodule for this:
![image](https://github.com/user-attachments/assets/125b2fab-2c51-4120-9d6f-4fb3a580944d)

Is there a specific reason for this to be a mixin?

Code after:
    @property
    def voice_id(self):
        voice_id_map = {
            Voice.LILY: "pFZP5JQG7iQjIQuC4Bku",
            Voice.DANIEL: "onwK4e9ZLuTAKqWW03F9",
            Voice.BRIAN: "nPczCjzI2devNBz1zQrb",
            Voice.JESSICA: "cgSgspJ2msm6clMCkdW9",
            Voice.CHARLOTTE: "XB0fDUnXU5powFXDhCwa",
            Voice.CALLUM: "N2lVS1w4EtoT3dr4eOWO",
            Voice.EVA: "FGY2WhTYpPnrIDTdsKH5",
        }
        return voice_id_map[self]

    def __str__(self):
        return self.value


class VisualMediaType(str, Enum):
    STOCK_VIDEOS = ("stockVideo",)
    MOVING_AI_IMAGES = ("movingImage",)
    AI_VIDEO = ("aiVideo",)


logger = logging.getLogger(__name__)


class AIShortformVideoCreatorBlock(Block):
    """Creates a short‑form text‑to‑video clip using stock or AI imagery."""

    class Input(BlockSchema):
        credentials: CredentialsMetaInput[
            Literal[ProviderName.REVID], Literal["api_key"]
        ] = CredentialsField(
            description="The revid.ai integration can be used with "
            "any API key with sufficient permissions for the blocks it is used on.",
        )
        script: str = SchemaField(
            description="""1. Use short and punctuated sentences\n\n2. Use linebreaks to create a new clip\n\n3. Text outside of brackets is spoken by the AI, and [text between brackets] will be used to guide the visual generation. For example, [close-up of a cat] will show a close-up of a cat.""",
            placeholder="[close-up of a cat] Meow!",
        )
        ratio: str = SchemaField(
            description="Aspect ratio of the video", default="9 / 16"
        )
        resolution: str = SchemaField(
            description="Resolution of the video", default="720p"
        )
        frame_rate: int = SchemaField(description="Frame rate of the video", default=60)
        generation_preset: GenerationPreset = SchemaField(
            description="Generation preset for visual style - only effects AI generated visuals",
            default=GenerationPreset.LEONARDO,
            placeholder=GenerationPreset.LEONARDO,