Tous les produits
Search
Centre de documentation

ApsaraVideo VOD:Bonnes pratiques pour les agents

Dernière mise à jour :Aug 20, 2026

Ce tutoriel vous guide dans la création d'un flux de travail ApsaraVideo VOD de bout en bout à l'aide d'un agent de codage IA. La démo côté serveur télécharge par lots des vidéos via une URL, les transcode automatiquement grâce à un groupe de modèles de transcodage spécifié et récupère les URL de lecture via des rappels d'événements. La démo côté client propose une application Android permettant la lecture de vidéos uniques ainsi qu'un visualiseur de streaming interactif en direct alimenté par AUI Kits.

Prérequis

Démo côté serveur

  • Une paire AccessKey pour un utilisateur RAM, stockée sous forme de variables d'environnement. N'utilisez pas une AccessKey de compte racine.

  • Python avec le SDK Alibaba Cloud pour VOD (aliyunsdkcore et aliyunsdkvod) installé.

  • Un endpoint HTTP accessible publiquement pour recevoir les rappels de notification d'événements.

  • Région VOD définie sur cn-shanghai (les téléchargements basés sur l'URL ne sont pris en charge que dans la région Chine (Shanghai)).

Démo côté client

  • Android Studio avec compileSdk 34 et minSdk 21.

  • Un fichier de licence AliPlayer (license.crt) placé dans app/src/main/assets/.

  • Modules AUI Kits (AUILiveRoomCore, AUILiveRoomViewer, AUIInteraction) importés dans le projet.

  • Un endpoint AppServer qui émet des jetons de visualisation pour le visualiseur de streaming interactif en direct.

Démo côté serveur : Téléchargement par lots, transcodage et lecture

Le code suivant soumet une tâche de téléchargement par lots avec un groupe de modèles de transcodage. Spécifier TemplateGroupId lors du téléchargement déclenche le transcodage automatique, ce qui évite d'avoir à effectuer un appel API distinct.

request = UploadMediaByURLRequest()
request.set_UploadURLs(','.join([urllib.parse.quote(url, safe='') for url in urls]))  # URLs must be encoded!
request.set_UploadMetadatas(json.dumps([{'SourceURL': urllib.parse.quote(u, safe=''), 'Title': f'Video{i}'} for i, u in enumerate(urls)]))
request.set_TemplateGroupId('your_template_group_id')  # Key: Specify this to auto-transcode after upload
response = json.loads(client.do_action_with_exception(request))
# Returns a list of JobIds. Track progress via event notifications.

Service de rappel HTTP (logique clé) : Renvoie immédiatement un code HTTP 200 pour éviter les nouvelles tentatives côté serveur (contrainte S-7).

class CallbackHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        body = json.loads(self.rfile.read(int(self.headers['Content-Length'])))
        self.send_response(200)  # Must return 200 immediately; retry is triggered after 5s timeout
        self.end_headers()

        if body['EventType'] == 'UploadByURLComplete' and body['Status'] == 'success':
            print(f"Upload complete: VideoId={body['VideoId']}, waiting for transcoding...")

        elif body['EventType'] == 'TranscodeComplete' and body['Status'] == 'success':
            # All transcodings complete -> Get playback URLs
            play_info = get_play_info(body['VideoId'])
            for stream in play_info['PlayInfoList']['PlayInfo']:
                print(f"  [{stream['Definition']}] {stream['PlayURL']}")

Obtenir l'URL de lecture (logique clé) :

request = GetPlayInfoRequest()
request.set_VideoId(video_id)
request.set_Formats('mp4,m3u8')
request.set_AuthTimeout(3600)  # URL is valid for 1 hour
response = json.loads(client.do_action_with_exception(request))
# response['PlayInfoList']['PlayInfo'] → playback URLs for each definition

Résultats d'exécution

Soumission du téléchargement par lots :

$ python vod_batch_upload.py

[1/2] Initializing VOD client... ✓ (region: cn-shanghai)
[2/2] Submitting batch upload job (3 videos)... ✓
  RequestId: 25818875-5F78-4AF6-D7393642CA58****
  JobId: ad90a501b1b9****  ← sample1.mp4
  JobId: bd81b612c2c8****  ← sample2.mp4
  JobId: ce72c723d3d9****  ← sample3.mp4

Subsequent steps are triggered automatically by event notifications:
  UploadByURLComplete → Auto Transcode → TranscodeComplete → GetPlayInfo

Réception des événements par le service de rappel :

$ python callback_server.py
Callback service started: http://0.0.0.0:8080 | Waiting for callbacks...

[UploadByURLComplete] VideoId=93ab850b**** | Status=success
  → Upload complete, waiting for auto-transcoding...

[StreamTranscodeComplete] VideoId=93ab850b**** | Status=success
  → LD definition transcoding complete (ready for playback)

[TranscodeComplete] VideoId=93ab850b**** | Status=success
  → All transcodings complete, getting playback URLs:
    [LD] https://vod.example.com/****/sample1-ld.mp4?auth_key=****
    [SD] https://vod.example.com/****/sample1-sd.mp4?auth_key=****
    [HD] https://vod.example.com/****/sample1-hd.mp4?auth_key=****

Récupération de documentation par l'agent

Prompt: "Batch upload + transcode + playback"
  │
  ▼
┌── llms.txt (Quick start matching + Common mistakes constraints) ──┐
│  ✓ "Batch URL upload"         → media-upload/url-based-upload.md  │
│  ✓ "Event notification"       → event-notification/event-notification_2.md  │
│  ✓ "Playback URL"             → api-reference/get-playback-url.md   │
│  ✓ "Python init"              → api-reference/initialization_2.md   │
│  ✓ "Auto transcode"           → media-processing/workflow.md        │
│  ✗ #1 Don't use root AK ✗ #3 Don't poll ✗ #5 URL encode ✗ #6 QPS backoff │
└────────────────────────┬─────────────────────────────────────┘
                         │
   ┌─────────────────────┼─────────────────────┐
   ▼                     ▼                     ▼
url-based-upload.md  event-notification_2.md get-playback-url.md
- UploadMediaByURL  - Event type list       - Request/response params
- URL must be encoded - HTTP callback format    - Definition enums
- Region limit      - Timeout & retry policy - QPS=360/s
- Max 20 URLs       - 5 sec timeout         - Status=Normal
   │                     │                     │
   ▼                     ▼                     ▼
   └────► initialization_2.md (SDK client constructor) ◄────┘
                         │
                         ▼
                  workflow.md (Auto-transcode with TemplateGroupId)
                         │
                         ▼
                Generate complete runnable code

Décisions de conception clés

Le tableau suivant répertorie les décisions de conception clés pour cette démo, avec des ID de contrainte explicites renvoyant à la référence structurée des contraintes.

Point de décision

Choix de l'agent

Base dans la documentation

Méthode de téléchargement

UploadMediaByURL

La documentation spécifie cette API pour le téléchargement par lots à partir d'une liste d'URL publiques.

Déclencheur de transcodage

Spécification de TemplateGroupId lors du téléchargement

La documentation indique que la spécification de TemplateGroupId lors du téléchargement déclenche le transcodage automatique, ce qui évite d'avoir à effectuer un appel API distinct.

Suivi de l'état

Rappel d'événement HTTP

Contrainte S-3 (OBLIGATOIRE) : Ne pas interroger (polling).

Moment pour obtenir l'URL de lecture

Après TranscodeComplete

La documentation indique que GetPlayInfo nécessite que l'état de la vidéo soit Normal.

Gestion des AccessKey

Variables d'environnement

Contraintes S-1, S-2 (OBLIGATOIRE) : Ne pas coder en dur.

Gestion des URL

quote(url, safe='')

Contrainte S-5 (OBLIGATOIRE) : Doit être encodé.

Région

cn-shanghai

La documentation indique que les téléchargements basés sur l'URL ne sont pris en charge que dans la région Chine (Shanghai).

Tolérance aux pannes

Nouvelle tentative avec backoff exponentiel

Contrainte S-6 (OBLIGATOIRE) : Backoff pour la limitation de débit.

Démo côté client : Lecteur Android et visualiseur en direct

Cette section crée une démo Android exécutable basée sur le flux de travail côté serveur. La démo lit un fichier MP4 avec un code minimal et intègre un visualiseur de streaming interactif en direct avec AUI Kits.

Invite soumise à l'agent :

Based on the client-side llms index (in directories like `client-side-player/`,
`client-side-upload/`, `client-side-short-video/`), implement a demo app for Android.
Specific requirements:
1. Select the minimum required dependency package to play the playback URL returned
   by the server-side demo's GetPlayInfo response.
2. In the same app, add another entry point to enter an interactive live streaming
   viewer using AUI Kits (with stream pulling, live comments (danmaku), likes,
   and gifts).
3. Make the package name, license, and AppServer domain configurable to avoid
   hardcoding.

Processus d'exécution de l'agent

Phase 1 : Lire l'index llms côté client et faire correspondre les scénarios

Quick start matching results:
  "Start VOD playback on Android"   → client-side-player/player-atomic-android.md
  "How to choose packages/dependencies" → client-side-player/player-overview.md
  "How to integrate the license"      → client-side-player/player-common-license.md
  "Interactive live streaming viewer" → client-side-player/player-kits-aui.md
  "Error codes 4400/4013"           → client-side-player/player-common-error-codes.md

Common mistakes matched:
  ✗ Initializing the license after creating the player → Must be done in Application.onCreate (C-1)
  ✗ Calling setSurface before the Surface is ready      → Must wait for surfaceCreated (C-2)
  ✗ Using the full-featured package by default        → Choose the minimal package for the scenario (C-3)
  ✗ Hardcoding the AppServer domain                   → Abstract to BuildConfig / gradle.properties (C-4)
  ✗ Calling PrivateService.init multiple times        → Initialize only once in the Application class (C-5)

Phase 2 : Charger la documentation détaillée à la demande

Document

Objectif

client-side-player/player-overview.md

Décision de sélection de package (BasicLive / UGC / InteractiveLive / Standard)

client-side-player/player-atomic-android.md

Dépendances Gradle, autorisations Manifest, obfuscation et code de lecture minimal

client-side-player/player-common-license.md

Timing d'intégration de la licence et dépannage des erreurs 4400/4013

client-side-player/player-kits-aui.md

Modules côté client AUI Kits et modèle de collaboration AppServer

client-side-player/player-common-error-codes.md

Référence rapide pour les échecs de démarrage de lecture

Phase 3 : Extraire les décisions clés

Package selection:
  Playback only          → AliVCSDK_BasicLive
  Playback + short video   → AliVCSDK_UGC
  Includes co-hosting/interactive live streaming  → AliVCSDK_InteractiveLive   ← This demo chooses this one
  Full-featured          → AliVCSDK_Standard / Premium

License:
  PrivateService.initService(ctx, licenseFile, licenseKey)
  Must be completed before the first call to createAliPlayer

AUI Kits:
  AppServer + client-side; AppServer issues Identity Token, Live Room Token, and IMS Token.
  Client: Three modules - AUILiveRoomCore, AUILiveRoomViewer, and AUIInteraction.

Configurer les dépendances du projet

Dans le fichier build.gradle au niveau du projet :

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url "https://maven.aliyun.com/nexus/content/repositories/releases" }
    }
}

Dans le fichier build.gradle au niveau de l'application :

android {
    compileSdk 34
    defaultConfig {
        applicationId "com.example.aliplayer.sample"
        minSdk 21
        targetSdk 34

        ndk { abiFilters "armeabi-v7a", "arm64-v8a" }

        buildConfigField "String", "APP_SERVER_HOST",
                "\"${project.findProperty('APP_SERVER_HOST') ?: 'https://your-appserver.example.com'}\""
        buildConfigField "String", "APP_SERVER_API_PREFIX", "\"/api/v1/live/\""
        buildConfigField "String", "LICENSE_KEY",
                "\"${project.findProperty('LICENSE_KEY') ?: ''}\""
    }
    buildFeatures { buildConfig true }
}

dependencies {
    implementation 'com.aliyun.aio:AliVCSDK_InteractiveLive:6.0.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.11.0'
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
    implementation 'com.google.code.gson:gson:2.10.1'
}

Configurer les autorisations et l'obfuscation

Dans le fichier AndroidManifest.xml :

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

Dans le fichier proguard-rules.pro :

-keep class com.alivc.**{*;}
-keep class com.aliyun.**{*;}
-keep class com.cicada.**{*;}
-dontwarn com.alivc.**
-dontwarn com.aliyun.**
-dontwarn com.cicada.**

Initialiser la licence

Créez le fichier SampleApp.java :

public class SampleApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // Place license.crt in app/src/main/assets/
        PrivateService.initService(getApplicationContext(),
                "file:///android_asset/license.crt",
                BuildConfig.LICENSE_KEY);
    }
}

Enregistrez SampleApp dans le fichier AndroidManifest.xml :

<application
    android:name=".SampleApp"
    android:label="@string/app_name"
    android:theme="@style/Theme.MaterialComponents.DayNight">
    <activity android:name=".MainActivity" android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".SimplePlayerActivity" />
</application>

Créer l'interface utilisateur de lecture vidéo unique

Créez le fichier de mise en page activity_player.xml :

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000">

    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:layout_gravity="center" />
</FrameLayout>

Créez le fichier SimplePlayerActivity.java :

public class SimplePlayerActivity extends AppCompatActivity {

    public static final String EXTRA_PLAY_URL = "play_url";

    private AliPlayer aliPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_player);

        SurfaceView surfaceView = findViewById(R.id.surfaceView);
        aliPlayer = AliPlayerFactory.createAliPlayer(getApplicationContext());

        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override public void surfaceCreated(SurfaceHolder h) {
                aliPlayer.setSurface(h.getSurface());
            }
            @Override public void surfaceChanged(SurfaceHolder h, int f, int w, int hh) {
                aliPlayer.surfaceChanged();
            }
            @Override public void surfaceDestroyed(SurfaceHolder h) {
                aliPlayer.setSurface(null);
            }
        });

        aliPlayer.setOnPreparedListener(() -> aliPlayer.start());
        aliPlayer.setOnErrorListener(err ->
                Log.e("AliPlayer", "code=" + err.getCode() + " msg=" + err.getMsg()));

        UrlSource source = new UrlSource();
        // Source: The playback URL (with auth_key) from the server-side demo's GetPlayInfo response
        String playUrl = getIntent().getStringExtra(EXTRA_PLAY_URL);
        source.setUri(playUrl != null ? playUrl : "https://your.cdn/test.mp4");
        aliPlayer.setDataSource(source);
        aliPlayer.setAutoPlay(true);
        aliPlayer.prepare();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (aliPlayer != null) {
            aliPlayer.stop();
            aliPlayer.release();
        }
    }
}

Si l'événement prepared et l'événement de première image apparaissent dans les journaux et que SurfaceView affiche correctement l'image, le lien sous-jacent est clair.

Intégrer le visualiseur en direct AUI Kits

Importer les modules AUI Kits

Dans le fichier settings.gradle :

include ':app',
        ':AUILiveRoomCore',
        ':AUILiveRoomViewer',
        ':AUIInteraction'

Dans le fichier build.gradle au niveau de l'application, ajoutez les dépendances suivantes :

implementation project(':AUILiveRoomCore')
implementation project(':AUILiveRoomViewer')
implementation project(':AUIInteraction')

Modèle de collaboration AppServer

Le client ne détient jamais directement les identifiants sensibles. À la place, l'AppServer les émet après authentification. Le diagramme suivant montre le flux de travail complet pour entrer dans une salle de diffusion en direct :

[Android App]                                [AppServer]
   │                                              │
   │── GET /api/v1/live/viewer/token?roomId=xxx ─►│
   │                                              ├── Authenticates and issues:
   │                                              │     userId / nick / pullUrl / imsToken
   │◄──────── 200 OK + ViewerTokenInfo ───────────┤
   │
   │── LiveRoomViewerActivity.start(params) ──►(Inside AUI Kits)
   │                                              │
   │   (AliPlayer for stream pulling + IMS for live comments)
  1. L'application Android envoie une requête GET /api/v1/live/viewer/token?roomId=xxx à l'AppServer avec l'état de connexion.

  2. L'AppServer vérifie l'état de connexion et émet userId, nick, pullUrl et imsToken.

  3. Une fois que l'application reçoit ViewerTokenInfo, elle appelle LiveRoomViewerActivity.start(params) pour entrer dans la salle de diffusion.

  4. En interne, AUI Kits utilise AliPlayer pour la récupération du flux et se connecte au Interactive Messaging Service (IMS) pour les commentaires en direct (danmaku), les mentions J'aime et les cadeaux.

AppServerClient (implémentation OkHttp)

Créez les fichiers AppServerClient.java et ViewerTokenInfo.java :

public class AppServerClient {

    public interface Callback {
        void onSuccess(ViewerTokenInfo info);
        void onFail(String msg);
    }

    private static final OkHttpClient client = new OkHttpClient();

    public static void fetchViewerToken(String roomId, Callback cb) {
        HttpUrl url = HttpUrl.parse(
                BuildConfig.APP_SERVER_HOST + BuildConfig.APP_SERVER_API_PREFIX + "viewer/token")
                .newBuilder()
                .addQueryParameter("roomId", roomId)
                .build();

        Request req = new Request.Builder()
                .url(url)
                .header("Authorization", "Bearer " + LoginManager.getToken())
                .build();

        client.newCall(req).enqueue(new okhttp3.Callback() {
            @Override public void onFailure(Call call, IOException e) {
                cb.onFail(e.getMessage());
            }
            @Override public void onResponse(Call call, Response resp) throws IOException {
                if (!resp.isSuccessful() || resp.body() == null) {
                    cb.onFail("HTTP " + resp.code());
                    return;
                }
                ViewerTokenInfo info = new Gson().fromJson(
                        resp.body().string(), ViewerTokenInfo.class);
                cb.onSuccess(info);
            }
        });
    }
}

public class ViewerTokenInfo {
    public String roomId;
    public String userId;
    public String nick;
    public String pullUrl;   // Any of rtmp, flv, m3u8, or artc
    public String imsToken;  // Interactive Messaging Service (IMS) Token
}

Combiner les entrées de la démo

Créez le fichier de mise en page activity_main.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:padding="24dp"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button android:id="@+id/btnSimple"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Simple Playback" />

    <Button android:id="@+id/btnLiveRoom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Interactive Live Viewer" />
</LinearLayout>

Créez le fichier MainActivity.java :

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btnSimple).setOnClickListener(v -> {
            Intent intent = new Intent(this, SimplePlayerActivity.class);
            // In a real application, pass the playback URL from the server-side demo's GetPlayInfo response here
            intent.putExtra(SimplePlayerActivity.EXTRA_PLAY_URL,
                    "https://vod.example.com/****/sample1-hd.mp4?auth_key=****");
            startActivity(intent);
        });

        findViewById(R.id.btnLiveRoom).setOnClickListener(v -> enterRoom("demo_room_001"));
    }

    private void enterRoom(String roomId) {
        AppServerClient.fetchViewerToken(roomId, new AppServerClient.Callback() {
            @Override public void onSuccess(ViewerTokenInfo info) {
                LiveRoomEnterParams params = new LiveRoomEnterParams.Builder()
                        .roomId(info.roomId)
                        .userId(info.userId)
                        .userNick(info.nick)
                        .pullUrl(info.pullUrl)
                        .imsToken(info.imsToken)
                        .build();
                LiveRoomViewerActivity.start(MainActivity.this, params);
            }
            @Override public void onFail(String msg) {
                Toast.makeText(MainActivity.this, "Failed to enter room: " + msg, Toast.LENGTH_LONG).show();
            }
        });
    }
}

Liste de vérification

Après avoir exécuté la démo, vérifiez le comportement de l'interface utilisateur et la sortie des journaux suivants :

  • Cliquez sur Simple Playback : L'activité SimplePlayerActivity démarre et la vidéo s'affiche sans interruption dans SurfaceView sans écran noir.

  • Cliquez sur Interactive Live Streaming Viewer : L'activité LiveRoomViewerActivity d'AUI Kits est lancée. AliPlayer affiche le flux vidéo de l'hôte. Les panneaux de commentaires en direct (danmaku), de mentions J'aime et de cadeaux en bas à droite sont fonctionnels.

  • Journaux logcat clés : L'apparition simultanée de AliPlayer: prepared, AliPlayer: first frame et IMS: connected indique que la récupération du flux et l'interaction sont prêtes.

Récupération de documentation par l'agent

Prompt: "Android playback + enter interactive live room"
  │
  ▼
┌── Client-side llms.txt (Quick start + Common mistakes) ────────┐
│  ✓ "Android playback"        → player-atomic-android.md         │
│  ✓ "How to choose package"   → player-overview.md               │
│  ✓ "License"                 → player-common-license.md          │
│  ✓ "AUI Kits interactive"    → player-kits-aui.md               │
│  ✓ "Error codes 4400/4013"   → player-common-error-codes.md     │
│  ✗ License must be initialized before player creation           │
│  ✗ Do not call setSurface before Surface is ready               │
│  ✗ Do not use the full-featured package by default              │
│  ✗ Do not hardcode the AppServer domain                         │
│  ✗ Call PrivateService.init only once in Application          │
└────────────────────────┬────────────────────────────────────┘
                         │
  ┌─────────────┬────────┴─────────┬─────────────┐
  ▼             ▼                  ▼             ▼
player-      player-atomic-   player-common-  player-kits-aui.md
overview.md  android.md       license.md      - AppServer collab
- Package matrix - gradle deps    - PrivateService - Three token types
- Scenario map - Manifest perms - 4400/4013     - Module breakdown
- SDK size     - Playback code  - Package/BundleID - 4-step client integration
  └─────────────┴────────┬─────────┴─────────────┘
                         │
                         ▼
              player-common-error-codes.md
              (Guidance for 4400/4013/4034/4036)
                         │
                         ▼
              Generate complete runnable Android Demo

Décisions de conception clés

Point de décision

Choix de l'agent

Base dans la documentation

Bundle SDK

AliVCSDK_InteractiveLive

La matrice de sélection dans player-overview.md recommande ce bundle pour les scénarios de streaming interactif en direct (contrainte C-3).

Timing de la licence

Application.onCreate

Contrainte C-1 (OBLIGATOIRE) : Doit être appelé avant createAliPlayer.

Liaison de surface

setSurface dans le rappel surfaceCreated

Contrainte C-2 (OBLIGATOIRE) : Modèle standard player-atomic-android.md.

Domaine AppServer

BuildConfig + gradle.properties

Contrainte C-4 (OBLIGATOIRE) : Ne pas coder en dur.

Intégration côté serveur

Réutilisation de l'URL de lecture de la réponse GetPlayInfo de la démo côté serveur

Cela garantit une cohérence de bout en bout entre les démos côté serveur et côté client.

Visualiseur en direct interactif

Trois modules AUI Kits (Core / Viewer / Interaction)

player-kits-aui.md : Guide principal d'intégration côté client.

Gestion des erreurs

setOnErrorListener est un rappel général pour le reporting d'événements. Les codes 4400, 4013, 4034 et 4036 sont réservés à la gestion personnalisée côté client.

player-common-error-codes.md

Liste de contrôle pré-lancement

Dimension

Élément de vérification

Licence

Les licences de test et de production ont été demandées et configurées dans leurs BuildConfigs respectifs.

Taille du package

abiFilters sont limités à armv7 + arm64. Le bundle SDK minimal est sélectionné en fonction du scénario.

Démarrage de la lecture

Des écouteurs pour les codes 4400/4013/4034/4036 sont implémentés pour la surveillance.

Salle de diffusion

Le renouvellement automatique des jetons IMS expirés est implémenté. L'AppServer a activé HTTPS et CORS.

Confidentialité

Les autorisations pour l'enregistrement audio, l'accès réseau et la lecture multimédia sont toutes déclarées dans la politique de confidentialité.

Version Canary

Publiez d'abord la nouvelle version pour 5 % des utilisateurs. Surveillez le temps de première image et les taux d'échec pendant 48 heures avant un déploiement complet.

Surveillance

Activez le service de surveillance de la qualité du lecteur (QoS) d'Alibaba Cloud et le traçage ponctuel.

Structure finale des répertoires

AliPlayerSampleApp/
├── app/
│   ├── src/main/
│   │   ├── assets/license.crt
│   │   ├── java/com/example/aliplayer/sample/
│   │   │   ├── SampleApp.java
│   │   │   ├── MainActivity.java
│   │   │   ├── SimplePlayerActivity.java         ← Simple Playback
│   │   │   ├── AppServerClient.java              ← Interactive Live Streaming
│   │   │   ├── ViewerTokenInfo.java
│   │   │   └── LoginManager.java
│   │   └── AndroidManifest.xml
│   └── build.gradle
├── AUILiveRoomCore/                               ← Interactive Live Streaming
├── AUILiveRoomViewer/                             ← Interactive Live Streaming
├── AUIInteraction/                                ← Interactive Live Streaming
├── gradle.properties (APP_SERVER_HOST / LICENSE_KEY)
├── settings.gradle
└── build.gradle

Les démos côté serveur et côté client forment un flux de travail complet et bouclé. En utilisant l'index llms.txt, l'Agent couvre le téléchargement vidéo, le transcodage automatique, la récupération de l'URL de lecture, la lecture vidéo de base et un visualiseur de streaming interactif en direct avec AUI Kits.

Annexe : Sélection et auto-vérification de l'agent

Cette section s'adresse aux développeurs qui n'ont pas installé d'agent de codage.

Quand utiliser un agent de codage

Cas d'utilisation

Est-ce nécessaire ?

Vous souhaitez que l'IA lise llms.txt, développe les sous-documents selon les besoins et génère un projet exécutable.

Oui

Vous souhaitez uniquement lire ce document pour comprendre l'architecture, puis copier et modifier manuellement le code.

Non. Un navigateur web suffit.

Vous souhaitez que l'IA ajoute, supprime et modifie directement des fichiers dans votre dépôt local et exécute des commandes pour valider les modifications.

Oui

Options recommandées

Catégorie

Nom

Type

Description

Recommandé

Qoder / Cursor / Claude Code

IDE de bureau ou CLI

Prend nativement en charge la récupération de documents longs à l'aide d'indexes de style llms.txt et fonctionne bien avec les SDK des fournisseurs cloud chinois. Qoder a été utilisé pour vérifier les démos de ce document.

Autre

-

-

Tout agent de codage capable d'accéder aux URL, d'écrire des fichiers locaux et d'appeler des commandes shell.

Remarque

Utilisez les liens d'installation du site web officiel du produit. Évitez d'utiliser des images tierces.

Auto-vérification minimale

Envoyez l'invite suivante à votre agent de codage pour vérifier ses capacités :

Please read https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/vod/llms/llms.txt,
and tell me:
1. How many top-level modules are in this index? What are they?
2. Which sub-documents are involved in the "batch upload + automatic transcoding + get audio/video playback URL" workflow? Please list their relative paths.
3. In the "Common mistakes to avoid" section, what are the notes related to "AccessKey"?

Réponses attendues :

  • Répertorie correctement les modules de niveau supérieur de llms.txt.

  • Répertorie les sous-documents largement cohérents avec le tableau de chargement à la demande de la démo côté serveur (téléchargement multimédia, notification d'événement, obtention de l'URL de lecture audio/vidéo, initialisation du SDK Python, flux de travail de traitement multimédia).

  • Indique clairement : N'utilisez pas une AccessKey de compte Alibaba Cloud. Utilisez plutôt un utilisateur RAM.

Un agent qui réussit les trois vérifications est prêt pour les démos ci-dessus.