All Products
Search
Document Center

ApsaraVideo VOD:Praktik terbaik untuk agent

Last Updated:Jun 06, 2026

Dokumen ini mendemonstrasikan praktik terbaik bagi Agent dalam mengakses layanan ApsaraVideo VOD Alibaba Cloud melalui indeks <a class="text-blue-link hover:text-black dark:text-blue-link-dark dark:hover:text-white" href="https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/vod/llms/llms.txt" id="cbd45583b0yim">llms.txt</a>, menggunakan dua demo end-to-end.

Catatan

Pastikan Anda telah membaca panduan memulai untuk Agen dan memahami struktur dasar file <a class="text-blue-link hover:text-black dark:text-blue-link-dark dark:hover:text-white" data-init-id="cbd45583b0yim" href="https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/vod/llms/llms.txt" id="78443e4819ujp">llms.txt</a>.

Catatan

Jika Anda belum menginstal Coding Agent, lihat apendiks: Pemilihan dan pemeriksaan mandiri Coding Agent.

Alur kerja agent untuk menggunakan llms.txt

Bagian ini menjelaskan alur kerja dan pembagian tugas antara developer dan Agent, yang menjadi fondasi bagi dua demo berikutnya. Tabel Keputusan Desain Utama pada setiap demo menunjukkan penerapan metodologi ini dalam skenario tertentu.

Pembagian peran: developer vs. Agent

Tabel berikut merinci pembagian tanggung jawab. Developer menyampaikan kebutuhan, menyiapkan lingkungan, dan menerima hasil, sedangkan Agent menangani pengambilan dokumen, desain solusi, dan pembuatan kode.

Fase

Developer

Agent

Inisiasi kebutuhan

Menjelaskan kebutuhan dalam bahasa alami.

-

Pengambilan dokumen

-

Membaca indeks llms.txt untuk mencocokkan skenario dan menemukan dokumentasi terperinci.

Pemahaman dokumen

-

Mengambil dokumentasi terperinci untuk mengekstraksi parameter request/respons, contoh kode, dan catatan penting.

Desain solusi

Memastikan atau menyesuaikan solusi.

Mengusulkan solusi implementasi berdasarkan dokumentasi dan menjelaskan pilihan teknologinya.

Pembuatan kode

-

Menghasilkan kode yang dapat dijalankan termasuk penanganan error.

Konfigurasi lingkungan

Mengonfigurasi AccessKey, menginstal dependensi, dan menyiapkan konsol.

Memberikan perintah dan panduan konfigurasi.

Eksekusi dan verifikasi

Menjalankan kode dan memastikan hasilnya.

Menjelaskan output dan melakukan troubleshooting masalah.

Alur kerja internal Agent

Agent memproses kebutuhan secara internal dalam empat fase berurutan, dengan output setiap fase menjadi input bagi fase berikutnya.

Fase 1: Membaca indeks llms.txt

Seluruh file indeks (~250 baris) dimuat dalam satu operasi untuk melakukan tiga tugas berikut:

  • Mengurai bagian Quick start guna memetakan skenario ke path dokumen.

  • Mengekstraksi bagian Common mistakes to avoid sebagai batasan ketat dalam pembuatan kode selanjutnya.

  • Menentukan topologi dokumen, termasuk modul utama dan submodulnya.

Fase 2: Mencocokkan skenario dan menemukan dokumentasi

  • Mencocokkan kata kunci kebutuhan dengan judul skenario di bagian Quick start.

  • Jika ditemukan skenario yang cocok, gunakan path dokumen yang sesuai secara langsung.

  • Jika tidak ada skenario yang cocok, pindai indeks modul untuk mengidentifikasi satu hingga tiga sub-dokumen yang paling relevan.

  • Buat URL: BASE_URL + url_encode(relative_path).

Fase 3: Mengambil dokumen dan mengekstraksi informasi

Elemen-elemen berikut diekstraksi dari sub-dokumen sebagai input untuk pembuatan kode: nama API, parameter request/respons, contoh kode, batas QPS, kode kesalahan, batasan wilayah, serta catatan tambahan.

Fase 4: Pembuatan kode

Sebelum membuat kode, Agent melakukan pemeriksaan mandiri terhadap daftar periksa Common mistakes to avoid:

  • Jika menggunakan AccessKey akun utama, gantilah dengan RAM user.

  • Jika menerapkan polling status, beralihlah ke notifikasi event.

  • Jika URL tidak di-encode, panggil url_encode.

  • Jika membuat kredensial baru untuk setiap request, gunakan kembali dan refresh objek Credential tersebut.

Agent juga menambahkan logika backoff QPS dan pemrosesan asinkron ke kode akhir.

Aturan pembuatan URL

File indeks menggunakan path relatif untuk mereferensikan sub-dokumen. Agent harus mengonversinya menjadi URL absolut saat mengambilnya.

Base URL: https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/vod/llms/
Document URL = Base URL + URL encoding(relative path, dengan "./" awal dihapus)

Contoh:
  Di llms.txt: [server-side upload](./媒体上传/服务端上传.md)
  Full URL: Base URL + %E5%AA%92%E4%BD%93%E4%B8%8A%E4%BC%A0/%E6%9C%8D%E5%8A%A1%E7%AB%AF%E4%B8%8A%E4%BC%A0.md

Demo end-to-end

Modul ini menyediakan dua demo end-to-end untuk sisi server dan sisi klien. PlayURL yang dikembalikan oleh operasi GetPlayInfo menghubungkan kedua sisi untuk membentuk alur kerja lengkap yang tertutup.

Prasyarat

Langkah

Lokasi

Aksi

1

Alibaba Cloud Console

Aktifkan layanan ApsaraVideo VOD

2

RAM Console

Buat RAM user, berikan kebijakan AliyunVODFullAccess, dan buat AccessKey

3

ApsaraVideo VOD Console

Konfigurasi kelompok template transkoding (catat TemplateGroupId)

4

ApsaraVideo VOD Console

Konfigurasi URL callback HTTP (Configuration Management > Callback Settings)

5

Terminal lokal

pip install aliyun-python-sdk-core aliyun-python-sdk-vod

6

Terminal lokal

Setel variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID=xxx dan ALIBABA_CLOUD_ACCESS_KEY_SECRET=xxx

Demo sisi server: Upload batch, transkoding, dan mendapatkan URL pemutaran

Demo ini menunjukkan bagaimana Agent menggunakan indeks llms.txt untuk membangun alur kerja lengkap di sisi server, mencakup upload batch URL, transkoding otomatis dengan menentukan kelompok template transkoding saat upload dan melacak progres melalui notifikasi event, serta mendapatkan URL pemutaran setelah transkoding selesai.

Prompt yang dikirimkan ke agent

Silakan gunakan dokumen llms.txt (https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/vod/llms/llms.txt) untuk mengimplementasikan alur kerja demo lengkap dalam Python untuk ApsaraVideo VOD, termasuk upload batch, transkoding otomatis, dan mendapatkan URL pemutaran.
Persyaratan spesifik:
1. Upload batch sekumpulan file video (diberikan sebagai daftar URL publik) ke ApsaraVideo VOD.
2. Secara otomatis memicu transkoding setelah upload selesai dengan menggunakan kelompok template transkoding yang ditentukan.
3. Setelah transkoding selesai, dapatkan URL pemutaran untuk setiap definisi video.
4. Diperlukan layanan callback HTTP untuk menerima notifikasi event.

Proses eksekusi Agent

Fase 1: Membaca llms.txt untuk mencocokkan skenario

Agent mencocokkan skenario dan batasan dalam indeks sebagai berikut:

Kata kunci Quick start → Path dokumen yang cocok:
  "Batch URL upload"         → media-upload/url-based-upload.md
  "Receive async event notifications" → event-notification/event-notification_2.md
  "Get playback URL for frontend"    → api-reference/get-playback-url.md
  "Python SDK initialization"       → api-reference/initialization_2.md
  "Auto-transcode on upload"        → media-processing/workflow.md

Kesalahan umum yang cocok:
  #1 Jangan gunakan AccessKey akun root  #3 Jangan polling status  #5 URL harus di-encode  #6 Gunakan backoff QPS

Fase 2: Memuat dokumentasi terperinci sesuai kebutuhan

Dokumen

Tujuan

media-upload/url-based-upload.md

Parameter dan batasan UploadMediaByURL

event-notification/event-notification_2.md

Mekanisme callback dan jenis event

api-reference/get-playback-url.md

Parameter GetPlayInfo dan struktur respons

api-reference/initialization_2.md

Metode inisialisasi Python SDK

media-processing/workflow.md

Mekanisme transkoding otomatis saat upload dengan menentukan kelompok template

Fase 3: Mengekstraksi informasi kunci

Upload batch: UploadMediaByURL
  - Asinkron, hanya di Tiongkok (Shanghai), maksimal 20 URL per request
  - URL harus di-encode
  - Dapat menentukan TemplateGroupId → Transkoding otomatis setelah upload

URL pemutaran: GetPlayInfo
  - Prasyarat: Status Video=Normal (setelah transkoding selesai)
  - Mengembalikan: PlayInfoList yang berisi PlayURL untuk setiap definisi

Notifikasi event: Callback HTTP POST
  - UploadByURLComplete    → Upload selesai
  - StreamTranscodeComplete → Transkoding definisi tunggal selesai (status siap diputar paling awal)
  - TranscodeComplete       → Semua transkoding selesai
  - Timeout callback adalah 5 detik, dengan maksimal 3 kali percobaan ulang

Fase 4: Menghasilkan kode

Agent menghasilkan kode inti berdasarkan informasi di atas.

Kode inti yang dihasilkan agent

Upload batch (logika utama): Membaca kredensial dari variabel lingkungan dan menerapkan encoding untuk semua URL.

# Inisialisasi - Baca AK dari variabel lingkungan, jangan hardcode (Kesalahan umum #1)
client = AcsClient(region_id='cn-shanghai', credential=AccessKeyCredential(
    os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'],
    os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
))

# Upload batch URL + tentukan kelompok template transkoding (transkode otomatis setelah upload)
request = UploadMediaByURLRequest()
request.set_UploadURLs(','.join([urllib.parse.quote(url, safe='') for url in urls]))  # URL harus di-encode!
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')  # Kunci: Tentukan ini untuk transkode otomatis setelah upload
response = json.loads(client.do_action_with_exception(request))
# Mengembalikan daftar JobIds. Lacak progres melalui notifikasi event.

Layanan callback HTTP (logika utama): Segera mengembalikan status 200 untuk mencegah percobaan ulang di sisi server.

class CallbackHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        body = json.loads(self.rfile.read(int(self.headers['Content-Length'])))
        self.send_response(200)  # Harus segera mengembalikan 200; percobaan ulang dipicu setelah timeout 5 detik
        self.end_headers()

        if body['EventType'] == 'UploadByURLComplete' and body['Status'] == 'success':
            print(f"Upload selesai: VideoId={body['VideoId']}, menunggu transkoding...")

        elif body['EventType'] == 'TranscodeComplete' and body['Status'] == 'success':
            # Semua transkoding selesai -> Dapatkan URL pemutaran
            play_info = get_play_info(body['VideoId'])
            for stream in play_info['PlayInfoList']['PlayInfo']:
                print(f"  [{stream['Definition']}] {stream['PlayURL']}")

Dapatkan URL pemutaran (logika utama):

request = GetPlayInfoRequest()
request.set_VideoId(video_id)
request.set_Formats('mp4,m3u8')
request.set_AuthTimeout(3600)  # URL berlaku selama 1 jam
response = json.loads(client.do_action_with_exception(request))
# response['PlayInfoList']['PlayInfo'] → URL pemutaran untuk setiap definisi

Hasil eksekusi

Mengirimkan upload batch:

$ python vod_batch_upload.py

[1/2] Menginisialisasi klien VOD... ✓ (wilayah: cn-shanghai)
[2/2] Mengirimkan tugas upload batch (3 video)... ✓
  RequestId: 25818875-5F78-4AF6-D7393642CA58****
  JobId: ad90a501b1b9****  ← sample1.mp4
  JobId: bd81b612c2c8****  ← sample2.mp4
  JobId: ce72c723d3d9****  ← sample3.mp4

Langkah selanjutnya dipicu secara otomatis oleh notifikasi event:
  UploadByURLComplete → Transkode Otomatis → TranscodeComplete → GetPlayInfo

Layanan callback menerima event:

$ python callback_server.py
Layanan callback dimulai: http://0.0.0.0:8080 | Menunggu callback...

[UploadByURLComplete] VideoId=93ab850b**** | Status=success
  → Upload selesai, menunggu transkoding otomatis...

[StreamTranscodeComplete] VideoId=93ab850b**** | Status=success
  → Transkoding definisi LD selesai (siap diputar)

[TranscodeComplete] VideoId=93ab850b**** | Status=success
  → Semua transkoding selesai, mendapatkan URL pemutaran:
    [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=****

Visualisasi pengambilan dokumen oleh Agent

Prompt: "Upload batch + transkode + pemutaran"
  │
  ▼
┌── llms.txt (Pencocokan Quick start + Batasan kesalahan umum) ──┐
│  ✓ "Batch URL upload"         → media-upload/url-based-upload.md  │
│  ✓ "Notifikasi event"         → event-notification/event-notification_2.md  │
│  ✓ "URL pemutaran"            → api-reference/get-playback-url.md   │
│  ✓ "Inisialisasi Python"      → api-reference/initialization_2.md   │
│  ✓ "Transkode otomatis"       → media-processing/workflow.md        │
│  ✗ #1 Jangan gunakan AK root ✗ #3 Jangan polling ✗ #5 Encode URL ✗ #6 Backoff QPS │
└────────────────────────┬─────────────────────────────────────┘
                         │
   ┌─────────────────────┼─────────────────────┐
   ▼                     ▼                     ▼
url-based-upload.md  event-notification_2.md get-playback-url.md
- UploadMediaByURL  - Daftar jenis event       - Parameter request/respons
- URL harus di-encode - Format callback HTTP    - Enum definisi
- Batasan wilayah   - Kebijakan timeout & retry - QPS=360/s
- Maks 20 URL       - Timeout 5 detik         - Status=Normal
   │                     │                     │
   ▼                     ▼                     ▼
   └────► initialization_2.md (konstruktor klien SDK) ◄────┘
                         │
                         ▼
                  workflow.md (Transkode otomatis dengan TemplateGroupId)
                         │
                         ▼
                Hasilkan kode lengkap yang dapat dijalankan

Keputusan desain utama

Tabel ini merinci keputusan desain utama untuk demo ini beserta dasarnya dalam dokumentasi.

Titik keputusan

Pilihan Agent

Dasar dalam dokumentasi

Metode upload

UploadMediaByURL

Dokumentasi menentukan API ini untuk upload batch dari daftar URL publik.

Pemicu transkoding

Tentukan TemplateGroupId saat upload

Dokumentasi menyatakan bahwa menentukan TemplateGroupId saat upload memicu transkoding otomatis, sehingga tidak perlu panggilan API terpisah.

Pelacakan status

Callback event HTTP

Kesalahan Umum #3: Hindari polling.

Waktu mendapatkan URL pemutaran

Setelah TranscodeComplete

Dokumentasi menyatakan bahwa GetPlayInfo memerlukan status video 'Normal'.

Manajemen AccessKey

variabel lingkungan

Kesalahan Umum #1: Jangan hardcode.

Penanganan URL

quote(url, safe='')

Kesalahan Umum #5: Harus di-encode.

Wilayah

cn-shanghai

Dokumentasi menyatakan bahwa upload berbasis URL hanya didukung di wilayah Tiongkok (Shanghai).

Toleransi kesalahan

Percobaan ulang backoff eksponensial

Kesalahan Umum #6: Backoff untuk pembatasan kecepatan.

Demo sisi klien: Pemutar Android dan penonton siaran langsung

Demo Android yang dapat dijalankan ini dibangun di atas alur kerja sisi server. Demo ini menunjukkan cara memutar file MP4 dengan kode minimal dan cara mengintegrasikan penonton siaran langsung interaktif menggunakan AUI Kits.

Prompt yang dikirimkan ke agent

Berdasarkan indeks llms sisi klien (di direktori seperti `client-side-player/`, `client-side-upload/`, `client-side-short-video/`), implementasikan aplikasi demo untuk Android.
Persyaratan spesifik:
1. Pilih paket dependensi minimum yang diperlukan untuk memutar URL pemutaran yang dikembalikan oleh respons GetPlayInfo demo sisi server.
2. Di aplikasi yang sama, tambahkan titik masuk lain untuk memasuki penonton siaran langsung interaktif menggunakan AUI Kits (dengan penarikan aliran, bullet screen, like, dan hadiah).
3. Buat nama paket, lisensi, dan domain AppServer dapat dikonfigurasi untuk menghindari hardcoding.

Proses eksekusi Agent

Fase 1: Membaca indeks llms sisi klien dan mencocokkan skenario

Hasil pencocokan Quick start:
  "Mulai pemutaran VOD di Android"   → client-side-player/player-atomic-android.md
  "Cara memilih paket/dependensi" → client-side-player/player-overview.md
  "Cara mengintegrasikan lisensi"      → client-side-player/player-common-license.md
  "Penonton siaran langsung interaktif" → client-side-player/player-kits-aui.md
  "Kode kesalahan 4400/4013"           → client-side-player/player-common-error-codes.md

Kesalahan umum yang cocok:
  ✗ Menginisialisasi lisensi setelah membuat pemutar → Harus dilakukan di Application.onCreate
  ✗ Memanggil setSurface sebelum Surface siap      → Harus menunggu surfaceCreated
  ✗ Menggunakan paket fitur lengkap secara default        → Pilih paket minimal sesuai skenario
  ✗ Hardcoding domain AppServer                   → Abstraksikan ke BuildConfig / gradle.properties
  ✗ Memanggil PrivateService.init beberapa kali        → Inisialisasi hanya sekali di kelas Application

Fase 2: Memuat dokumentasi terperinci sesuai kebutuhan

Dokumen

Tujuan

client-side-player/player-overview.md

Keputusan pemilihan paket (BasicLive / UGC / InteractiveLive / Standard)

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

Dependensi Gradle, izin Manifest, obfuscation, dan kode pemutaran minimal

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

Waktu integrasi lisensi dan troubleshooting untuk error 4400/4013

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

Modul sisi klien AUI Kits dan model kolaborasi AppServer

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

Referensi cepat untuk kegagalan memulai pemutaran

Fase 3: Mengekstraksi keputusan kunci

Pemilihan paket:
  Hanya pemutaran          → AliVCSDK_BasicLive
  Pemutaran + video pendek   → AliVCSDK_UGC
  Termasuk co-hosting/siaran langsung interaktif  → AliVCSDK_InteractiveLive   ← Demo ini memilih yang ini
  Fitur lengkap          → AliVCSDK_Standard / Premium

Lisensi:
  PrivateService.initService(ctx, licenseFile, licenseKey)
  Harus diselesaikan sebelum panggilan pertama ke createAliPlayer

AUI Kits:
  AppServer + sisi klien; AppServer mengeluarkan Identity Token, Live Room Token, dan IMS Token.
  Klien: Tiga modul - AUILiveRoomCore, AUILiveRoomViewer, dan AUIInteraction.

Hasil eksekusi

Integrasi pemutar cepat

Dependensi proyek

Di file build.gradle tingkat proyek:

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

Di file build.gradle tingkat aplikasi:

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

Izin dan obfuscation

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

Di file proguard-rules.pro:

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

Inisialisasi lisensi

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

Daftarkan di file 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>
UI pemutaran video tunggal

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

Buat file 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();
        // Sumber: URL pemutaran (dengan auth_key) dari respons GetPlayInfo demo sisi server
        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();
        }
    }
}

Jika event prepared dan event frame pertama muncul di log serta SurfaceView merender gambar dengan benar, koneksi dasar telah berhasil.

Penonton siaran langsung AUI Kits

Impor modul AUI Kits

Di file settings.gradle:

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

Di file build.gradle tingkat aplikasi:

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

Model kolaborasi AppServer

Klien tidak menyimpan langsung kredensial sensitif seperti IMS Token. Sebagai gantinya, AppServer mengeluarkannya setelah autentikasi. Alur kerja lengkap untuk memasuki ruang siaran langsung adalah sebagai berikut:

[Aplikasi Android]                                [AppServer]
   │                                              │
   │── GET /api/v1/live/viewer/token?roomId=xxx ─►│
   │                                              ├── Autentikasi dan mengeluarkan:
   │                                              │     userId / nick / pullUrl / imsToken
   │◄──────── 200 OK + ViewerTokenInfo ───────────┤
   │
   │── LiveRoomViewerActivity.start(params) ──►(Di dalam AUI Kits)
   │                                              │
   │   (AliPlayer untuk penarikan aliran + IMS untuk bullet screen)                 │
  1. Aplikasi Android mengirim permintaan GET /api/v1/live/viewer/token?roomId=xxx ke AppServer dengan status login.

  2. AppServer memverifikasi status login dan mengeluarkan userId, nick, pullUrl, dan imsToken.

  3. Setelah aplikasi menerima ViewerTokenInfo, aplikasi memanggil LiveRoomViewerActivity.start(params) untuk memasuki ruang siaran langsung.

  4. Secara internal, AUI Kits menggunakan AliPlayer untuk penarikan aliran dan terhubung ke Interactive Messaging Service (IMS) guna mendukung fitur bullet screen, like, dan hadiah.

AppServerClient (implementasi OkHttp)

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;   // Salah satu dari rtmp, flv, m3u8, atau artc
    public String imsToken;  // Token Interactive Messaging Service (IMS)
}
Gabungkan dua entri demo

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

Buat file 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);
            // Di aplikasi nyata, berikan URL pemutaran dari respons GetPlayInfo demo sisi server di sini
            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, "Gagal memasuki ruang: " + msg, Toast.LENGTH_LONG).show();
            }
        });
    }
}

Daftar periksa verifikasi

Setelah menjalankan demo, verifikasi perilaku UI dan output log berikut:

  • Klik Simple Playback: SimplePlayerActivity dimulai, dan video diputar dengan lancar di SurfaceView tanpa layar hitam.

  • Klik Interactive Live Streaming Viewer: LiveRoomViewerActivity AUI Kits diluncurkan; AliPlayer menampilkan feed video host; panel bullet screen, like, dan hadiah di pojok kanan bawah berfungsi.

  • Log logcat utama: Kemunculan bersamaan AliPlayer: prepared, AliPlayer: first frame, dan IMS: connected menunjukkan bahwa penarikan aliran dan interaksi sudah siap.

Visualisasi pengambilan dokumen oleh Agent

Prompt: "Pemutaran Android + masuk ruang siaran langsung interaktif"
  │
  ▼
┌── Client-side llms.txt (Quick start + Kesalahan umum) ────────┐
│  ✓ "Pemutaran Android"       → player-atomic-android.md         │
│  ✓ "Cara memilih paket"      → player-overview.md               │
│  ✓ "Lisensi"                 → player-common-license.md          │
│  ✓ "Interaktif AUI Kits"     → player-kits-aui.md               │
│  ✓ "Kode kesalahan 4400/4013"→ player-common-error-codes.md     │
│  ✗ Lisensi harus diinisialisasi sebelum pembuatan pemutar       │
│  ✗ Jangan panggil setSurface sebelum Surface siap               │
│  ✗ Jangan gunakan paket fitur lengkap secara default            │
│  ✗ Jangan hardcode domain AppServer                             │
│  ✗ Panggil PrivateService.init hanya sekali di Application      │
└────────────────────────┬────────────────────────────────────┘
                         │
  ┌─────────────┬────────┴─────────┬─────────────┐
  ▼             ▼                  ▼             ▼
player-      player-atomic-   player-common-  player-kits-aui.md
overview.md  android.md       license.md      - Kolaborasi AppServer
- Matriks paket - dependensi gradle - PrivateService - Tiga jenis token
- Peta skenario - izin Manifest - 4400/4013     - Rincian modul
- Ukuran SDK   - kode pemutaran - Package/BundleID - Integrasi klien 4 langkah
  └─────────────┴────────┬─────────┴─────────────┘
                         │
                         ▼
              player-common-error-codes.md
              (Panduan untuk 4400/4013/4034/4036)
                         │
                         ▼
              Hasilkan Demo Android lengkap yang dapat dijalankan

Keputusan desain utama

Titik keputusan

Pilihan Agent

Dasar dalam dokumentasi

Bundel SDK

AliVCSDK_InteractiveLive

Matriks pemilihan di player-overview.md merekomendasikan bundle ini untuk skenario siaran langsung interaktif.

Waktu lisensi

Application.onCreate

player-common-license.md: Harus dipanggil sebelum createAliPlayer.

Pengikatan Permukaan

setSurface dalam callback surfaceCreated

Templat standar player-atomic-android.md.

Domain AppServer

BuildConfig + gradle.properties

Kesalahan Umum: Jangan hardcode.

Integrasi sisi server

Gunakan kembali URL pemutaran dari respons GetPlayInfo demo sisi server

Hal ini memastikan konsistensi end-to-end antara demo sisi server dan sisi klien.

Penonton siaran langsung interaktif

Tiga modul AUI Kits (Core / Viewer / Interaction)

player-kits-aui.md: Panduan integrasi sisi klien utama.

Penanganan error

setOnErrorListener adalah callback umum untuk pelaporan event. Kode 4400, 4013, 4034, dan 4036 diperuntukkan bagi penanganan khusus sisi klien.

player-common-error-codes.md

Daftar periksa pra-peluncuran (Android)

Dimensi

Item periksa

Lisensi

Lisensi pengujian dan produksi telah diajukan dan dikonfigurasi di BuildConfig masing-masing.

Ukuran paket

abiFilters dibatasi hanya untuk armv7 + arm64; bundle SDK minimal dipilih berdasarkan skenario.

Memulai pemutaran

Listener untuk 4400/4013/4034/4036 diimplementasikan untuk pemantauan.

Ruang siaran langsung

Pembaruan otomatis untuk IMS Token yang kadaluarsa diimplementasikan; AppServer telah mengaktifkan HTTPS dan CORS.

Privasi

Izin untuk perekaman audio, akses jaringan, dan pembacaan media semuanya dinyatakan dalam kebijakan privasi.

Rilis canary

Pertama, rilis versi baru ke 5% pengguna. Pantau waktu frame pertama dan tingkat kegagalan selama 48 jam sebelum peluncuran penuh.

Pemantauan

Aktifkan layanan pemantauan kualitas pemutar (QoS) dan pelacakan titik tunggal Alibaba Cloud.

Struktur direktori akhir

AliPlayerSampleApp/
├── app/
│   ├── src/main/
│   │   ├── assets/license.crt
│   │   ├── java/com/example/aliplayer/sample/
│   │   │   ├── SampleApp.java
│   │   │   ├── MainActivity.java
│   │   │   ├── SimplePlayerActivity.java         ← Pemutaran Sederhana
│   │   │   ├── AppServerClient.java              ← Siaran Langsung Interaktif
│   │   │   ├── ViewerTokenInfo.java
│   │   │   └── LoginManager.java
│   │   └── AndroidManifest.xml
│   └── build.gradle
├── AUILiveRoomCore/                               ← Siaran Langsung Interaktif
├── AUILiveRoomViewer/                             ← Siaran Langsung Interaktif
├── AUIInteraction/                                ← Siaran Langsung Interaktif
├── gradle.properties (APP_SERVER_HOST / LICENSE_KEY)
├── settings.gradle
└── build.gradle

Demo sisi server dan sisi klien kini membentuk alur kerja lengkap yang tertutup. Alur kerja ini, yang dihasilkan oleh Agent menggunakan indeks llms.txt, mencakup pengunggahan video, transkoding otomatis, pengambilan URL pemutaran, pemutaran video dasar, dan penonton siaran langsung interaktif menggunakan AUI Kits.

Apendiks: Pemilihan dan pemeriksaan mandiri Agent

Apendiks ini ditujukan bagi developer yang belum menggunakan atau menginstal Coding Agent.

Kapan menggunakan Coding Agent

Kasus penggunaan

Apakah diperlukan?

Anda ingin AI membaca llms.txt, memperluas sub-dokumen sesuai kebutuhan, dan menghasilkan proyek yang dapat dijalankan.

Ya

Anda hanya ingin membaca dokumen ini untuk memahami arsitektur, lalu menyalin dan memodifikasi kode secara manual.

Tidak. Browser web sudah cukup.

Anda ingin AI secara langsung menambah, menghapus, dan memodifikasi file di repositori lokal Anda serta menjalankan perintah untuk memvalidasi perubahan.

Ya

Opsi yang direkomendasikan

Kategori

Nama

Jenis

Deskripsi

Direkomendasikan

Qoder / Cursor / Claude Code

IDE Desktop atau CLI

Secara native mendukung pengambilan dokumen panjang menggunakan indeks bergaya llms.txt dan bekerja dengan baik dengan SDK dari penyedia cloud Tiongkok. Kami menggunakan Qoder untuk memverifikasi demo dalam dokumen ini.

Lainnya

-

-

Coding Agent apa pun yang dapat mengakses URL, menulis file lokal, dan memanggil perintah shell.

Catatan

Gunakan tautan instalasi dari situs web resmi produk. Hindari menggunakan image pihak ketiga.

Pemeriksaan mandiri minimum

Kirimkan prompt berikut ke Coding Agent Anda untuk memverifikasi kemampuannya:

Silakan baca https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/vod/llms/llms.txt,
dan beri tahu saya:
1. Berapa banyak modul tingkat atas dalam indeks ini? Apa saja?
2. Sub-dokumen mana yang terlibat dalam alur kerja "upload batch + transkoding otomatis + dapatkan URL pemutaran audio/video"? Sebutkan path relatifnya.
3. Di bagian "Common mistakes to avoid", apa catatan yang terkait dengan "AccessKey"?

Jawaban yang diharapkan:

  • Menyebutkan dengan benar modul tingkat atas dari llms.txt.

  • Memberikan daftar sub-dokumen yang sebagian besar konsisten dengan tabel pemuatan sesuai kebutuhan dalam demo sisi server (upload media, notifikasi event, dapatkan URL pemutaran audio/video, inisialisasi Python SDK, alur kerja pemrosesan media).

  • Menyatakan dengan jelas: Jangan gunakan AccessKey Akun Alibaba Cloud. Gunakan RAM user sebagai gantinya.

Agent yang lulus ketiga pemeriksaan ini siap untuk demo dalam dokumen ini.