すべてのプロダクト
Search
ドキュメントセンター

ApsaraVideo VOD:エージェントのベストプラクティス

最終更新日:Aug 21, 2026

このチュートリアルでは、AI コーディングエージェントを使用して、エンドツーエンドの ApsaraVideo VOD ワークフローを構築します。サーバーサイドのデモでは、URL を使用して動画をバッチアップロードし、指定されたトランスコードテンプレートグループで自動的にトランスコードし、イベントコールバックを通じて再生 URL を取得します。クライアントサイドのデモでは、単一動画の再生機能と AUI Kits を利用したインタラクティブライブストリーミングビューアーを備えた Android アプリを提供します。

前提条件

サーバーサイドデモ

  • 環境変数として保存された RAM ユーザーの AccessKey ペア。ルートアカウントの AccessKey は使用しないでください。

  • Alibaba Cloud SDK for VOD (aliyunsdkcore および aliyunsdkvod) がインストールされた Python。

  • イベント通知のコールバックを受信するための、パブリックにアクセス可能な HTTP エンドポイント。

  • VOD のリージョンが cn-shanghai に設定されていること (URL ベースのアップロードは中国 (上海) リージョンでのみサポートされています)。

クライアントサイドデモ

  • compileSdk 34 および minSdk 21 を備えた Android Studio。

  • app/src/main/assets/ に配置された AliPlayer のライセンスファイル (license.crt)。

  • プロジェクトにインポートされた AUI Kits モジュール (AUILiveRoomCoreAUILiveRoomViewerAUIInteraction)。

  • インタラクティブライブストリーミングの視聴者向けにビューワートークンを発行する AppServer エンドポイント。

サーバーサイドデモ:バッチアップロード、トランスコード、再生

以下のコードは、トランスコードテンプレートグループを指定してバッチアップロードタスクを送信します。アップロード時に TemplateGroupId を指定すると、自動的にトランスコードがトリガーされるため、別途 API を呼び出す必要はありません。

request = UploadMediaByURLRequest()
request.set_UploadURLs(','.join([urllib.parse.quote(url, safe='') for url in urls]))  # URL はエンコード必須です。
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')  # 重要:アップロード後に自動トランスコードするには、これを指定します
response = json.loads(client.do_action_with_exception(request))
# JobId のリストを返します。イベント通知で進捗を追跡します。

HTTP コールバックサービス (主要ロジック):サーバーサイドでの再試行を防ぐため、直ちに HTTP 200 を返します (制約 S-7)。

class CallbackHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        body = json.loads(self.rfile.read(int(self.headers['Content-Length'])))
        self.send_response(200)  # 直ちに 200 を返す必要があります。5秒のタイムアウト後に再試行がトリガーされます
        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':
            # すべてのトランスコードが完了 -> 再生 URL を取得
            play_info = get_play_info(body['VideoId'])
            for stream in play_info['PlayInfoList']['PlayInfo']:
                print(f"  [{stream['Definition']}] {stream['PlayURL']}")

再生 URL の取得 (主要ロジック)

request = GetPlayInfoRequest()
request.set_VideoId(video_id)
request.set_Formats('mp4,m3u8')
request.set_AuthTimeout(3600)  # URL は 1 時間有効です
response = json.loads(client.do_action_with_exception(request))
# response['PlayInfoList']['PlayInfo'] → 各解像度の再生 URL

実行結果

バッチアップロードの送信

$ 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

コールバックサービスがイベントを受信

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

[UploadByURLComplete] VideoId=93ab850b**** | Status=success
  → アップロード完了、自動トランスコードを待機中...

[StreamTranscodeComplete] VideoId=93ab850b**** | Status=success
  → LD 解像度のトランスコード完了 (再生準備完了)

[TranscodeComplete] VideoId=93ab850b**** | Status=success
  → すべてのトランスコード完了、再生 URL を取得:
    [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=****

エージェントによるドキュメント検索

プロンプト:「バッチアップロード + トランスコード + 再生」
  │
  ▼
┌── llms.txt (クイックスタートのマッチング + よくある間違いの制約) ──┐
│  ✓ 「URLによるバッチアップロード」 → media-upload/url-based-upload.md  │
│  ✓ 「イベント通知」       → event-notification/event-notification_2.md  │
│  ✓ 「再生 URL」             → api-reference/get-playback-url.md   │
│  ✓ 「Python初期化」              → api-reference/initialization_2.md   │
│  ✓ 「自動トランスコード」           → media-processing/workflow.md        │
│  ✗ #1 ルート AK を使用しない ✗ #3 ポーリングしない ✗ #5 URLをエンコードしない ✗ #6 QPS バックオフ │
└────────────────────────┬─────────────────────────────────────┘
                         │
   ┌─────────────────────┼─────────────────────┐
   ▼                     ▼                     ▼
url-based-upload.md  event-notification_2.md get-playback-url.md
- UploadMediaByURL  - イベントタイプ一覧       - リクエスト/レスポンスパラメーター
- URL はエンコード必須 - HTTPコールバック形式    - 解像度Enum
- リージョン制限      - タイムアウトと再試行ポリシー - QPS=360/s
- 最大 20 URL       - 5秒タイムアウト         - Status=正常
   │                     │                     │
   ▼                     ▼                     ▼
   └────► initialization_2.md (SDKクライアントコンストラクター) ◄────┘
                         │
                         ▼
                  workflow.md (TemplateGroupIdによる自動トランスコード)
                         │
                         ▼
                実行可能な完全なコードを生成

主要な設計判断

次の表は、このデモにおける主要な設計判断と、構造化された制約リファレンスに遡る明示的な制約IDの一覧です。

決定事項

エージェントの選択

ドキュメントにおける根拠

アップロード方法

UploadMediaByURL

ドキュメントでは、公開URLのリストからバッチアップロードするためにこのAPIを指定しています。

トランスコードのトリガー

アップロード時にTemplateGroupIdを指定

ドキュメントには、アップロード時に TemplateGroupId を指定すると自動トランスコードがトリガーされ、別途 API を呼び出す必要がなくなると記載されています。

ステータス追跡

HTTPイベントコールバック

制約 S-3 (MUST):ポーリングしないでください。

再生 URL の取得タイミング

TranscodeComplete後

ドキュメントには、GetPlayInfo は動画のステータスが Normal である必要があると記載されています。

AccessKeyの管理

環境変数

制約 S-1, S-2 (MUST):ハードコードしないでください。

URLの処理

quote(url, safe='')

制約 S-5 (MUST):エンコードする必要があります。

リージョン

cn-shanghai

ドキュメントには、URLベースのアップロードは中国 (上海) リージョンでのみサポートされていると記載されています。

フォールトトレランス

指数バックオフによる再試行

制約 S-6 (MUST):スロットリングのためのバックオフ。

クライアントサイドデモ:Android プレイヤーとライブビューアー

このセクションでは、サーバーサイドのワークフローをベースに、実行可能な Android デモを構築します。このデモは、最小限のコードで MP4 ファイルを再生し、AUI Kits を使用してインタラクティブライブストリーミングビューアーを統合します。

エージェントに送信されたプロンプト

クライアントサイドの llms インデックス (`client-side-player/`、`client-side-upload/`、`client-side-short-video/` などのディレクトリ内) に基づいて、Android 用のデモアプリを実装してください。
具体的な要件:
1. サーバーサイドデモの GetPlayInfo レスポンスで返される再生 URL を再生するために、
   最小限必要な依存パッケージを選択してください。
2. 同じアプリに、AUI Kits (ストリームプル、ライブコメント (弾幕)、
   「いいね」、ギフト機能付き) を使用してインタラクティブライブストリーミングビューアーに入るための
   別のエントリーポイントを追加してください。
3. パッケージ名、ライセンス、AppServer ドメインを、ハードコードを避けるために
   設定可能にしてください。

エージェントの実行プロセス

フェーズ1:クライアントサイドの llms インデックスを読み取り、シナリオを照合

クイックスタートのマッチング結果:
  「Android で VOD 再生を開始」   → client-side-player/player-atomic-android.md
  「パッケージ/依存関係の選択方法」 → client-side-player/player-overview.md
  「ライセンスの統合方法」      → client-side-player/player-common-license.md
  「インタラクティブライブストリーミングビューアー」 → client-side-player/player-kits-aui.md
  「エラーコード4400/4013」           → client-side-player/player-common-error-codes.md

照合されたよくある間違い:
  ✗ プレイヤー作成後にライセンスを初期化 → Application.onCreateで実行する必要があります (C-1)
  ✗ Surfaceの準備が整う前にsetSurfaceを呼び出し      → surfaceCreatedを待つ必要があります (C-2)
  ✗ デフォルトでフル機能パッケージを使用        → シナリオに合わせて最小パッケージを選択してください (C-3)
  ✗ AppServer ドメインをハードコード                   → BuildConfig / gradle.propertiesに抽象化してください (C-4)
  ✗ PrivateService.init を複数回呼び出し        → Applicationクラスで一度だけ初期化してください (C-5)

フェーズ2:詳細なドキュメントをオンデマンドで読み込む

ドキュメント

目的

client-side-player/player-overview.md

パッケージ選択の決定 (BasicLive / UGC / InteractiveLive / Standard)

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

Gradleの依存関係、マニフェストの権限、難読化、および最小限の再生コード

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

ライセンス統合のタイミングとエラー4400/4013のトラブルシューティング

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

AUI KitsクライアントサイドモジュールとAppServer連携モデル

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

再生開始失敗時のクイックリファレンス

フェーズ3:主要な決定事項の抽出

パッケージ選択:
  再生のみ          → AliVCSDK_BasicLive
  再生 + ショートビデオ   → AliVCSDK_UGC
  共催/インタラクティブライブストリーミングを含む  → AliVCSDK_InteractiveLive   ← このデモではこれを選択
  フル機能          → AliVCSDK_Standard / Premium

ライセンス:
  PrivateService.initService(ctx, licenseFile, licenseKey)
  createAliPlayer の最初の呼び出しの前に完了する必要があります

AUI Kits:
  AppServer + クライアントサイド;AppServer は ID トークン、ライブルームトークン、IMS トークンを発行します。
  クライアント:3つのモジュール - AUILiveRoomCore、AUILiveRoomViewer、AUIInteraction。

プロジェクトの依存関係の設定

プロジェクトレベルの build.gradle ファイルで:

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

アプリレベルの build.gradle ファイルで:

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'
}

権限と難読化の設定

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" />

proguard-rules.pro ファイルで:

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

ライセンスの初期化

SampleApp.java ファイルを作成します:

public class SampleApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // license.crtをapp/src/main/assets/に配置します
        PrivateService.initService(getApplicationContext(),
                "file:///android_asset/license.crt",
                BuildConfig.LICENSE_KEY);
    }
}

AndroidManifest.xml ファイルに SampleApp を登録します:

<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>

単一動画再生UIの構築

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>

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();
        // ソース:サーバーサイドデモの GetPlayInfo レスポンスから取得した再生 URL (auth_key 付き)
        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();
        }
    }
}

ログに prepared イベントと初回フレームイベントが表示され、SurfaceView が画像を正しくレンダリングすれば、基盤となるリンクは正常です。

AUI Kitsライブビューアーの統合

AUI Kitsモジュールのインポート

settings.gradle ファイルで:

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

アプリレベルの build.gradle ファイルに、以下の依存関係を追加します:

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

AppServer 連携モデル

クライアントは機密性の高い認証情報を直接保持しません。代わりに、AppServerが認証後にそれらを発行します。次の図は、ライブルームに入るための完全なワークフローを示しています:

[Androidアプリ]                            [AppServer]
   │                                              │
   │── GET /api/v1/live/viewer/token?roomId=xxx ─►│
   │                                              ├── 認証して発行:
   │                                              │     userId / nick / pullUrl / imsToken
   │◄──────── 200 OK + ViewerTokenInfo ───────────┤
   │
   │── LiveRoomViewerActivity.start(params) ──►(AUI Kits内部)
   │                                              │
   │   (ストリームプル用のAliPlayer + ライブコメント用のIMS)
  1. Androidアプリは、ログイン状態とともに GET /api/v1/live/viewer/token?roomId=xxx リクエストをAppServerに送信します。

  2. AppServerはログイン状態を検証し、userIdnickpullUrl、および imsToken を発行します。

  3. アプリが ViewerTokenInfo を受信した後、LiveRoomViewerActivity.start(params) を呼び出してライブルームに入ります。

  4. 内部的に、AUI KitsはAliPlayerを使用してストリームプルを行い、Interactive Messaging Service (IMS) に接続してライブコメント (弾幕)、「いいね」、ギフト機能を実現します。

AppServerClient (OkHttp 実装)

AppServerClient.javaViewerTokenInfo.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;   // RTMP、FLV、M3U8、または ARTC のいずれか
    public String imsToken;  // Interactive Messaging Service (IMS) トークン
}

デモエントリーの結合

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>

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);
            // 実際のアプリケーションでは、サーバーサイドデモの GetPlayInfo レスポンスから取得した再生 URL をここで渡します
            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();
            }
        });
    }
}

検証チェックリスト

デモを実行した後、以下のUIの動作とログ出力を検証します:

  • [Simple Playback] をクリック:SimplePlayerActivity が開始され、ビデオが SurfaceView で黒い画面にならずにスムーズに再生される。

  • [Interactive Live Viewer] をクリック:AUI Kits の LiveRoomViewerActivity が起動される。AliPlayer がホストのビデオフィードを表示する。右下のライブコメント (弾幕)、「いいね」、ギフトパネルが機能する。

  • 主要な logcat ログ: AliPlayer: preparedAliPlayer: first frame、および IMS: connected が同時に表示されると、ストリームのプルとインタラクションの両方の準備が整ったことを示します。

エージェントによるドキュメント検索

プロンプト:「Android 再生 + インタラクティブライブルームへの入室」
  │
  ▼
┌── クライアントサイドllms.txt (クイックスタート + よくある間違い) ────────┐
│  ✓ 「Android 再生」        → player-atomic-android.md         │
│  ✓ 「パッケージ選択方法」   → player-overview.md               │
│  ✓ 「ライセンス」                 → player-common-license.md          │
│  ✓ 「AUI Kitsインタラクティブ」    → player-kits-aui.md               │
│  ✓ 「エラーコード4400/4013」   → player-common-error-codes.md     │
│  ✗ プレイヤー作成後にライセンスを初期化           │
│  ✗ Surfaceの準備が整う前にsetSurfaceを呼び出し               │
│  ✗ デフォルトでフル機能パッケージを使用              │
│  ✗ AppServer ドメインをハードコード                         │
│  ✗ PrivateService.init は Application で一度だけ呼び出し          │
└────────────────────────┬────────────────────────────────────┘
                         │
  ┌─────────────┬────────┴─────────┬─────────────┐
  ▼             ▼                  ▼             ▼
player-      player-atomic-   player-common-  player-kits-aui.md
overview.md  android.md       license.md      - AppServer連携
- パッケージマトリックス - gradle依存関係    - PrivateService - 3種類のトークン
- シナリオマップ - マニフェスト権限 - 4400/4013     - モジュール分割
- SDKサイズ     - 再生コード  - Package/BundleID - 4ステップのクライアント統合
  └─────────────┴────────┬─────────┴─────────────┘
                         │
                         ▼
              player-common-error-codes.md
              (4400/4013/4034/4036 のガイダンス)
                         │
                         ▼
              実行可能な完全なAndroidデモを生成

主要な設計判断

決定事項

エージェントの選択

ドキュメントにおける根拠

SDKバンドル

AliVCSDK_InteractiveLive

player-overview.md の選択マトリックスでは、インタラクティブライブストリーミングシナリオにこのバンドルを推奨します (制約 C-3)。

ライセンスのタイミング

Application.onCreate

制約 C-1 (MUST):createAliPlayer の前に呼び出す必要があります。

サーフェスのバインド

setSurfaceをsurfaceCreatedコールバック内で

制約 C-2 (MUST):player-atomic-android.md の標準テンプレート。

AppServerドメイン

BuildConfig + gradle.properties

制約 C-4 (MUST):ハードコードしないでください。

サーバーサイドの統合

サーバーサイドデモの GetPlayInfo レスポンスから取得した再生 URL を再利用

これにより、サーバーサイドとクライアントサイドのデモ間でエンドツーエンドの一貫性が確保されます。

インタラクティブライブビューアー

AUI Kitsの3つのモジュール (Core / Viewer / Interaction)

player-kits-aui.md:主要なクライアントサイドの統合ガイド。

エラーハンドリング

setOnErrorListener はイベント報告用の汎用コールバックです。コード4400、4013、4034、4036は、カスタムのクライアントサイド処理用に予約されています。

player-common-error-codes.md

リリース前チェックリスト

項目

チェック項目

ライセンス

テスト用および本番用のライセンスが申請され、それぞれの BuildConfig に設定されている。

パッケージサイズ

abiFilters は armv7 + arm64 に限定されている。シナリオに基づいて最小のSDKバンドルが選択されている。

再生開始

モニタリングのために 4400/4013/4034/4036 のリスナーが実装されている。

ライブルーム

期限切れの IMS トークンの自動更新が実装されている。AppServer で HTTPS と CORS が有効になっている。

プライバシー

音声録音、ネットワークアクセス、メディア読み取りの権限はすべてプライバシーポリシーで宣言されている。

カナリアリリース

まず、ユーザーの5%に新バージョンをリリースする。完全なロールアウトの前に、48時間、初回フレーム時間と失敗率を監視する。

モニタリング

Alibaba Cloud のプレイヤー品質モニタリングサービス (QoS) とシングルポイントトレーシングを有効にする。

最終的なディレクトリ構造

AliPlayerSampleApp/
├── app/
│   ├── src/main/
│   │   ├── assets/license.crt
│   │   ├── java/com/example/aliplayer/sample/
│   │   │   ├── SampleApp.java
│   │   │   ├── MainActivity.java
│   │   │   ├── SimplePlayerActivity.java         ← シンプル再生
│   │   │   ├── AppServerClient.java              ← インタラクティブライブストリーミング
│   │   │   ├── ViewerTokenInfo.java
│   │   │   └── LoginManager.java
│   │   └── AndroidManifest.xml
│   └── build.gradle
├── AUILiveRoomCore/                               ← インタラクティブライブストリーミング
├── AUILiveRoomViewer/                             ← インタラクティブライブストリーミング
├── AUIInteraction/                                ← インタラクティブライブストリーミング
├── gradle.properties (APP_SERVER_HOST / LICENSE_KEY)
├── settings.gradle
└── build.gradle

サーバーサイドとクライアントサイドのデモは、完全なクローズドループワークフローを形成します。llms.txt インデックスを使用することで、エージェントは動画のアップロード、自動トランスコード、再生 URL の取得、基本的な動画再生、そして AUI Kits を使用したインタラクティブライブストリーミングビューアーまでをカバーします。

付録:エージェントの選択と自己チェック

このセクションは、コーディングエージェントをインストールしていない開発者向けです。

コーディングエージェントを使用するタイミング

ユースケース

必要ですか?

AIに llms.txt を読み込ませ、必要に応じてサブドキュメントを展開し、実行可能なプロジェクトを生成させたい。

はい

このドキュメントを読んでアーキテクチャを理解し、コードをコピーして手動で修正したいだけ。

いいえ。Web ブラウザーで十分です。

AIにローカルリポジトリ内のファイルを直接追加、削除、変更させ、コマンドを実行して変更を検証させたい。

はい

推奨オプション

カテゴリ

名称

タイプ

説明

推奨

Qoder / Cursor / Claude Code

デスクトップIDEまたはCLI

llms.txt スタイルのインデックスを使用した長文ドキュメント検索をネイティブにサポートし、中国のクラウドプロバイダーの SDK とも良好に連携します。このドキュメントのデモの検証には Qoder が使用されました。

その他

-

-

URL にアクセスし、ローカルファイルを書き込み、シェルコマンドを呼び出すことができる任意のコーディングエージェント。

説明

公式製品Webサイトのインストールリンクを使用してください。サードパーティのイメージは使用しないでください。

最小限の自己チェック

コーディングエージェントに以下のプロンプトを送信して、その能力を検証してください:

https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/vod/llms/llms.txt を読み、
以下の点について教えてください:
1. このインデックスにはいくつのトップレベルモジュールがありますか?それらは何ですか?
2. 「バッチアップロード + 自動トランスコード + 音声/動画再生 URL の取得」ワークフローには、どのサブドキュメントが関与していますか?相対パスをリストアップしてください。
3. 「避けるべきよくある間違い」セクションで、「AccessKey」に関連する注意点は何ですか?

期待される回答

  • llms.txt からトップレベルモジュールを正しくリストアップする。

  • サーバーサイドデモのオンデマンド読み込みテーブルとほぼ一致するサブドキュメント (メディアアップロード、イベント通知、音声/動画再生 URL の取得、Python SDK初期化、メディア処理ワークフロー) をリストアップする。

  • 明確に次のように述べる:Alibaba Cloud アカウントの AccessKey を使用しないでください。代わりに RAM ユーザーを使用してください。

3つのチェックすべてに合格したエージェントは、上記のデモを実行する準備ができています。