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 (
aliyunsdkcoreetaliyunsdkvod) 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 34etminSdk 21.Un fichier de licence AliPlayer (
license.crt) placé dansapp/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 |
|
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 |
|
Gestion des AccessKey |
Variables d'environnement |
Contraintes S-1, S-2 (OBLIGATOIRE) : Ne pas coder en dur. |
|
Gestion des URL |
|
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)
L'application Android envoie une requête
GET /api/v1/live/viewer/token?roomId=xxxà l'AppServer avec l'état de connexion.L'AppServer vérifie l'état de connexion et émet
userId,nick,pullUrletimsToken.Une fois que l'application reçoit
ViewerTokenInfo, elle appelleLiveRoomViewerActivity.start(params)pour entrer dans la salle de diffusion.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é
SimplePlayerActivitydémarre et la vidéo s'affiche sans interruption dansSurfaceViewsans écran noir.Cliquez sur Interactive Live Streaming Viewer : L'activité
LiveRoomViewerActivityd'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 frameetIMS: connectedindique 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 |
|
Timing de la licence |
Application.onCreate |
Contrainte C-1 (OBLIGATOIRE) : Doit être appelé avant |
|
Liaison de surface |
|
Contrainte C-2 (OBLIGATOIRE) : Modèle standard |
|
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) |
|
|
Gestion des erreurs |
|
|
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 |
|
|
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 |
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 |
|
Autre |
- |
- |
Tout agent de codage capable d'accéder aux URL, d'écrire des fichiers locaux et d'appeler des commandes shell. |
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.