> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# HappyHorse 1.0 Videogenerierung

>  - Videogenerierungsmodell Alibaba Cloud Bailian HappyHorse 1.0 (einheitlicher Einstieg, Auto-Routing über ein einziges Modell)
- Automatisches Routing nach Parametern: T2V (nur prompt) / I2V (first_frame_image) / R2V (image_urls) / EDIT (video_url)
- Unterstützt Auflösungen 720P/1080P und jede ganzzahlige Dauer von 3 bis 15 Sekunden
- Abrechnung nur nach Auflösung × Dauer (Sekunden), unabhängig von der Funktion 

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.apimart.ai/v1/videos/generations \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "model": "happyhorse-1.0",
      "prompt": "A little girl walking down the road, cinematic feel",
      "resolution": "1080P",
      "size": "16:9",
      "duration": 5,
      "seed": 42
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.apimart.ai/v1/videos/generations"

  payload = {
      "model": "happyhorse-1.0",
      "prompt": "A little girl walking down the road, cinematic feel",
      "resolution": "1080P",
      "size": "16:9",
      "duration": 5,
      "seed": 42
  }

  headers = {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json"
  }

  response = requests.post(url, json=payload, headers=headers)

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const url = "https://api.apimart.ai/v1/videos/generations";

  const payload = {
    model: "happyhorse-1.0",
    prompt: "A little girl walking down the road, cinematic feel",
    resolution: "1080P",
    size: "16:9",
    duration: 5,
    seed: 42
  };

  const headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
  };

  fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(payload)
  })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io/ioutil"
      "net/http"
  )

  func main() {
      url := "https://api.apimart.ai/v1/videos/generations"

      payload := map[string]interface{}{
          "model":      "happyhorse-1.0",
          "prompt":     "A little girl walking down the road, cinematic feel",
          "resolution": "1080P",
          "size":       "16:9",
          "duration":   5,
          "seed":       42,
      }

      jsonData, _ := json.Marshal(payload)

      req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
      req.Header.Set("Authorization", "Bearer <token>")
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      body, _ := ioutil.ReadAll(resp.Body)
      fmt.Println(string(body))
  }
  ```

  ```java Java theme={null}
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.net.URI;

  public class Main {
      public static void main(String[] args) throws Exception {
          String url = "https://api.apimart.ai/v1/videos/generations";

          String payload = """
          {
            "model": "happyhorse-1.0",
            "prompt": "A little girl walking down the road, cinematic feel",
            "resolution": "1080P",
            "size": "16:9",
            "duration": 5,
            "seed": 42
          }
          """;

          HttpClient client = HttpClient.newHttpClient();
          HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create(url))
              .header("Authorization", "Bearer <token>")
              .header("Content-Type", "application/json")
              .POST(HttpRequest.BodyPublishers.ofString(payload))
              .build();

          HttpResponse<String> response = client.send(request,
              HttpResponse.BodyHandlers.ofString());

          System.out.println(response.body());
      }
  }
  ```

  ```php PHP theme={null}
  <?php

  $url = "https://api.apimart.ai/v1/videos/generations";

  $payload = [
      "model" => "happyhorse-1.0",
      "prompt" => "A little girl walking down the road, cinematic feel",
      "resolution" => "1080P",
      "size" => "16:9",
      "duration" => 5,
      "seed" => 42
  ];

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "Authorization: Bearer <token>",
      "Content-Type: application/json"
  ]);

  $response = curl_exec($ch);
  curl_close($ch);

  echo $response;
  ?>
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'
  require 'uri'

  url = URI("https://api.apimart.ai/v1/videos/generations")

  payload = {
    model: "happyhorse-1.0",
    prompt: "A little girl walking down the road, cinematic feel",
    resolution: "1080P",
    size: "16:9",
    duration: 5,
    seed: 42
  }

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(url)
  request["Authorization"] = "Bearer <token>"
  request["Content-Type"] = "application/json"
  request.body = payload.to_json

  response = http.request(request)
  puts response.body
  ```

  ```swift Swift theme={null}
  import Foundation

  let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!

  let payload: [String: Any] = [
      "model": "happyhorse-1.0",
      "prompt": "A little girl walking down the road, cinematic feel",
      "resolution": "1080P",
      "size": "16:9",
      "duration": 5,
      "seed": 42
  ]

  var request = URLRequest(url: url)
  request.httpMethod = "POST"
  request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
  request.setValue("application/json", forHTTPHeaderField: "Content-Type")
  request.httpBody = try? JSONSerialization.data(withJSONObject: payload)

  let task = URLSession.shared.dataTask(with: request) { data, response, error in
      if let error = error {
          print("Error: \(error)")
          return
      }

      if let data = data, let responseString = String(data: data, encoding: .utf8) {
          print(responseString)
      }
  }

  task.resume()
  ```

  ```csharp C# theme={null}
  using System;
  using System.Net.Http;
  using System.Text;
  using System.Threading.Tasks;

  class Program
  {
      static async Task Main(string[] args)
      {
          var url = "https://api.apimart.ai/v1/videos/generations";

          var payload = @"{
              ""model"": ""happyhorse-1.0"",
              ""prompt"": ""A little girl walking down the road, cinematic feel"",
              ""resolution"": ""1080P"",
              ""size"": ""16:9"",
              ""duration"": 5,
              ""seed"": 42
          }";

          using var client = new HttpClient();
          client.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");

          var content = new StringContent(payload, Encoding.UTF8, "application/json");
          var response = await client.PostAsync(url, content);
          var result = await response.Content.ReadAsStringAsync();

          Console.WriteLine(result);
      }
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "code": 200,
    "data": [
      {
        "status": "submitted",
        "task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
      }
    ]
  }
  ```

  ```json 400 theme={null}
  {
    "error": {
      "code": 400,
      "message": "Invalid request parameters",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 401 theme={null}
  {
    "error": {
      "code": 401,
      "message": "Invalid authentication credentials",
      "type": "authentication_error"
    }
  }
  ```

  ```json 402 theme={null}
  {
    "error": {
      "code": 402,
      "message": "Insufficient balance. Please top up your account",
      "type": "payment_required"
    }
  }
  ```

  ```json 429 theme={null}
  {
    "error": {
      "code": 429,
      "message": "Rate limit exceeded. Please try again later",
      "type": "rate_limit_error"
    }
  }
  ```

  ```json 500 theme={null}
  {
    "error": {
      "code": 500,
      "message": "Internal server error. Please try again later",
      "type": "server_error"
    }
  }
  ```
</ResponseExample>

## Autorisierung

<ParamField header="Authorization" type="string" required>
  Alle API-Endpunkte erfordern eine Bearer-Token-Authentifizierung

  API-Key abrufen:

  Besuchen Sie die [Seite zur API-Key-Verwaltung](https://apimart.ai/keys), um Ihren API-Key zu erhalten

  Fügen Sie ihn zum Request-Header hinzu:

  ```
  Authorization: Bearer YOUR_API_KEY
  ```
</ParamField>

## Modus-Routing

`happyhorse-1.0` ist der einheitliche Einstieg für Text-to-Video / Image-to-Video / Reference-Image-to-Video / Video Edit. Das Backend ermittelt den Modus automatisch anhand der eingehenden Parameter. **Alle Modi werden nach derselben Regel abgerechnet (nur Auflösung × Sekunden)**:

| Übergebene Felder                                                                       | Routet zu                      | Modusbeschreibung                         |
| --------------------------------------------------------------------------------------- | ------------------------------ | ----------------------------------------- |
| Nur `prompt`                                                                            | Text-to-Video (T2V)            | Video rein aus Text generieren            |
| `prompt` + `first_frame_image`                                                          | Image-to-Video (I2V)           | Animation aus einem Erstbild              |
| `prompt` + `image_urls` (1–9 Bilder)                                                    | Reference-Image-to-Video (R2V) | Neue Szene aus Referenzbildern generieren |
| `prompt` + `video_url` (optional `image_urls` 0–5 als Stilreferenzen / `audio_setting`) | Video Edit (EDIT)              | Quellvideo umschreiben / umstilisieren    |

**Routing-Priorität** (hoch nach niedrig): `video_url` > `first_frame_image` > `image_urls` > nur `prompt`.

**Regeln zur gegenseitigen Ausschließlichkeit**: Die drei Medienfelder (`first_frame_image` / `image_urls` / `video_url`) sind **paarweise gegenseitig ausschließend**. Die einzige gültige Kombination ist `video_url + image_urls` (EDIT-Modus + Referenzbilder). Werden zwei sich ausschließende Felder übergeben, wird 400 `mixed_media_not_allowed` zurückgegeben.

## Anfrageparameter

<ParamField body="model" type="string" required>
  Name des Videogenerierungsmodells, fest auf `happyhorse-1.0`
</ParamField>

<ParamField body="prompt" type="string">
  Beschreibung des Videoinhalts, bis zu 2500 Zeichen; darf keine Sondertoken enthalten

  * **T2V- / R2V- / EDIT-Modi**: erforderlich
  * **I2V-Modus**: optional, aber empfohlen zur Steuerung von Kamerabewegung und Aktionen

  Beispiel: `"A little girl walking down the road, cinematic feel"`
</ParamField>

<ParamField body="first_frame_image" type="string">
  Erstes Einzelbild, löst **I2V** (Image-to-Video) aus. Unterstützt URL oder base64 (`data:image/<mime>;base64,<payload>`, das Gateway lädt es automatisch in OSS hoch)

  Schließt sich gegenseitig aus mit `image_urls` / `video_url`

  <Note>
    **Anforderungen an das Erstbild:**

    * Format: JPEG / JPG / PNG / BMP / WEBP
    * Kurze Seite: ≥ 300 px
    * Seitenverhältnis: `1:2.5` bis `2.5:1`
    * Dateigröße: ≤ 10 MB
  </Note>
</ParamField>

<ParamField body="image_urls" type="array<string>">
  Bilder-Array:

  * **R2V-Modus** (nur `image_urls` angegeben): 1–9 Bilder, dienen als Subjekt-/Stilreferenzen zur Generierung einer neuen Szene
  * **EDIT-Modus** (zusammen mit `video_url` angegeben): 0–5 Bilder, dienen als Stilreferenz

  Unterstützt URL oder base64

  Schließt sich gegenseitig aus mit `first_frame_image`; kann mit `video_url` kombiniert werden

  <Note>
    **Anforderungen an Referenzbilder:**

    * Format: JPEG / JPG / PNG / BMP / WEBP
    * Kurze Seite: empfohlen ≥ 720p
    * Seitenverhältnis: kurz / lang ≥ 0,4
    * Dateigröße: ≤ 10 MB
    * Anzahl: R2V muss 1–9 sein; EDIT bis zu 5
  </Note>
</ParamField>

<ParamField body="video_url" type="string">
  URL des Quellvideos, löst **EDIT** (Video Edit) aus. **Base64 wird nicht unterstützt** — geben Sie einen HTTP/HTTPS-Direktlink an

  Schließt sich gegenseitig aus mit `first_frame_image`; kann mit `image_urls` (≤ 5) kombiniert werden

  <Note>
    **Anforderungen an das Quellvideo:**

    * Dauer: 3–60 Sekunden (> 15s wird vom Upstream automatisch von 0 bis 15s gekürzt)
    * Auflösung: mindestens 480p, kurze Seite ≥ 360
    * Seitenverhältnis: `1:8` bis `8:1`
    * Format: MP4 / MOV (H.264 empfohlen)
    * Bildrate: > 8 fps
    * Dateigröße: ≤ 100 MB
  </Note>

  <Warning>
    **Im EDIT-Modus entspricht die Dauer des generierten Videos der Dauer des Quellvideos** (begrenzt auf die gekürzten 15s, wenn die Quelle länger ist). Der Parameter `duration` hat hier keine Wirkung. Um die Ausgabelänge zu steuern, schneiden Sie das Quellvideo vor dem Hochladen auf die Zieldauer.
  </Warning>
</ParamField>

<ParamField body="audio_setting" type="string" default="auto">
  Audio-Einstellung, **nur im EDIT-Modus wirksam** (`video_url` muss übergeben werden)

  Optionen:

  * `auto` – Audio automatisch generieren (Standard)
  * `origin` – Audiospur des Quellvideos beibehalten

  <Warning>
    Wird dieses Feld außerhalb des EDIT-Modus übergeben, wird 400 `audio_setting_only_for_edit` zurückgegeben
  </Warning>
</ParamField>

<ParamField body="resolution" type="string" default="1080P">
  Videoauflösung (beeinflusst die Abrechnung)

  Optionen:

  * `720P` – Standard
  * `1080P` – Hohe Auflösung (Standard)
</ParamField>

<ParamField body="duration" type="integer" default="5">
  Videodauer in Sekunden (beeinflusst die Abrechnung)

  Unterstützter Bereich: jede Ganzzahl von `3` bis `15`

  Standard: `5`

  <Warning>
    **Hat im EDIT-Modus keine Wirkung (wenn `video_url` angegeben ist)**: Die Dauer des generierten Videos entspricht der des Quellvideos (Abrechnung nach den gekürzten 15s, wenn die Quelle länger als 15s ist). Um die Ausgabelänge zu steuern, schneiden Sie das Quellvideo zuerst.
  </Warning>
</ParamField>

<ParamField body="size" type="string" default="16:9">
  Seitenverhältnis

  Unterstützte Formate:

  * `16:9` – Querformat Breitbild (Standard)
  * `9:16` – Hochformat
  * `1:1` – Quadrat
  * `4:3` – Querformat
  * `3:4` – Hochformat

  <Warning>
    **In den Modi I2V / EDIT ignoriert** — das Ausgabe-Seitenverhältnis wird automatisch durch das Eingabemedium (Erstbild / Quellvideo) bestimmt
  </Warning>
</ParamField>

<ParamField body="watermark" type="boolean" default="false">
  Soll dem generierten Video ein Wasserzeichen hinzugefügt werden?

  * `true`: Wasserzeichen hinzufügen
  * `false`: kein Wasserzeichen (Standard)
</ParamField>

<ParamField body="seed" type="integer">
  Zufallsseed zur Steuerung der Zufälligkeit des generierten Inhalts

  Wertebereich: `[0, 2147483647]`. Wenn weggelassen, wird ein zufälliger Seed verwendet.

  <Note>
    * Bei identischen Anfragen erzeugt das Modell unterschiedliche Ergebnisse, wenn unterschiedliche Seed-Werte empfangen werden (z. B. ohne Seed)
    * Bei identischen Anfragen erzeugt das Modell ähnliche Ergebnisse, wenn derselbe Seed-Wert empfangen wird, eine exakte Übereinstimmung ist jedoch nicht garantiert
  </Note>
</ParamField>

## Antwort

<ResponseField name="code" type="integer">
  Statuscode der Antwort, 200 bei Erfolg
</ResponseField>

<ResponseField name="data" type="array">
  Datenarray der Antwort

  <Expandable title="Array-Elemente">
    <ResponseField name="status" type="string">
      Aufgabenstatus, `submitted` bei der Erstübermittlung
    </ResponseField>

    <ResponseField name="task_id" type="string">
      Eindeutige Aufgabenkennung zur Abfrage von Status und Ergebnissen
    </ResponseField>
  </Expandable>
</ResponseField>

## Anwendungsfälle

### Fall 1: Text-zu-Video T2V (einfachste Anfrage)

```json theme={null}
{
  "model": "happyhorse-1.0",
  "prompt": "A little girl walking down the road, cinematic feel"
}
```

### Fall 2: Text-zu-Video T2V (vollständige Parameter)

```json theme={null}
{
  "model": "happyhorse-1.0",
  "prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
  "resolution": "1080P",
  "size": "16:9",
  "duration": 8,
  "seed": 42
}
```

### Fall 3: Bild-zu-Video I2V (first\_frame\_image)

```json theme={null}
{
  "model": "happyhorse-1.0",
  "prompt": "Bring the scene in the image to life",
  "first_frame_image": "https://example.com/first_frame.png",
  "resolution": "1080P",
  "duration": 5
}
```

### Fall 4: Referenz-Bild-zu-Video R2V (mehrere Referenzen)

```json theme={null}
{
  "model": "happyhorse-1.0",
  "prompt": "The protagonist from image 1 runs through the scene from image 2, then picks up the prop from image 3. Keep a 3D cartoon style with smooth motion.",
  "image_urls": [
    "https://example.com/img_01.jpg",
    "https://example.com/img_02.png",
    "https://example.com/img_03.jpeg"
  ],
  "resolution": "1080P",
  "size": "16:9",
  "duration": 5
}
```

### Fall 5: Video Edit EDIT (Originalton beibehalten + Stilreferenz)

```json theme={null}
{
  "model": "happyhorse-1.0",
  "prompt": "Convert the character in the video to a cartoon style, preserving the original motion",
  "video_url": "https://example.com/source.mp4",
  "image_urls": [
    "https://example.com/style_ref.jpg"
  ],
  "resolution": "1080P",
  "audio_setting": "origin",
  "seed": 42
}
```

### Fall 6: 720P zur Kosteneinsparung

```json theme={null}
{
  "model": "happyhorse-1.0",
  "prompt": "Waves crashing on the beach at sunset",
  "resolution": "720P",
  "size": "16:9",
  "duration": 5
}
```

## Leitfaden zur Moduswahl

| Anforderung                                                       | Empfohlene Vorgehensweise                                                                    |
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| Video nur aus Text generieren                                     | Nur `prompt` übergeben (T2V)                                                                 |
| Ein Bild „lebendig" machen (als Erstbild verwenden)               | `first_frame_image` übergeben (I2V)                                                          |
| Eine neue Szene aus einer Sammlung von Referenzbildern generieren | `image_urls` übergeben (1–9, R2V)                                                            |
| Ein vorhandenes Video umschreiben / umstilisieren                 | `video_url` übergeben (EDIT), optional mit `image_urls` (0–5) als Stilreferenzen kombinieren |
| Kosten sparen                                                     | `resolution: "720P"` verwenden                                                               |

## Tipps zur Nutzung

1. **Logik des einheitlichen Einstiegs**: Die Eingabefelder bestimmen den Modus. Beachten Sie, dass die drei Medienfelder (`first_frame_image` / `image_urls` / `video_url`) paarweise gegenseitig ausschließend sind
2. **`size` wirkt nur in T2V/R2V**: In den Modi I2V / EDIT wird `size` ignoriert — das Ausgabe-Seitenverhältnis wird durch das Eingabemedium bestimmt
3. **Dauer**: 5–10 Sekunden ist der optimale Bereich. Zu kurz führt zu ruckartiger Bewegung; zu lang erhöht die Upstream-Verarbeitungszeit erheblich
4. **Qualität des Erstbildes**: klar, gut komponiert, Subjekt zentriert — verbessert die I2V-Ausgabe deutlich
5. **Prompt-Formulierung**: Beschreiben Sie Bewegung / Kamera / Atmosphäre (z. B. „slow push-in, cinematic, warm tones") für bessere Ergebnisse als rein statische Szenenbeschreibungen
6. **EDIT-Eingangsvideo**: > 15 Sekunden wird vom Upstream automatisch von 0 bis 15s gekürzt. Wenn Sie andere Abschnitte benötigen, schneiden Sie das Video zuerst selbst zu

<Note>
  **Aufgabenergebnisse abfragen**

  Die Videogenerierung ist eine asynchrone Aufgabe, die nach der Übermittlung eine `task_id` zurückgibt. Verwenden Sie den Endpunkt [Aufgabenstatus abrufen](/de/api-reference/tasks/status), um den Generierungsfortschritt und die Ergebnisse abzufragen.
</Note>
