Bu eğitimde, uçtan uca bir ApsaraVideo VOD iş akışı oluşturmak üzere bir AI Kodlama Aracısı kullanırsınız. Sunucu tarafı demo, videoları URL üzerinden toplu olarak yükler, belirtilen bir kod dönüştürme şablon grubuyla otomatik olarak kodunu dönüştürür ve olay geri aramaları yoluyla oynatma URL'lerini alır. İstemci tarafı demo, AUI Kits tarafından desteklenen etkileşimli canlı yayın izleyicisi ve tek video oynatma özelliğine sahip bir Android uygulaması sağlar.
Ön koşullar
Sunucu tarafı demo
Ortam değişkenleri olarak depolanan bir RAM kullanıcısı AccessKey çifti. Kök hesap AccessKey'i kullanmayın.
Alibaba Cloud SDK for VOD (
aliyunsdkcorevealiyunsdkvod) yüklü Python.Olay bildirimi geri aramalarını almak için genel olarak erişilebilir bir HTTP uç noktası.
VOD bölgesi
cn-shanghaiolarak ayarlanmış (URL tabanlı yüklemeler yalnızca Çin (Şanghay) bölgesinde desteklenir).
İstemci tarafı demo
compileSdk 34veminSdk 21sürümlerine sahip Android Studio.app/src/main/assets/dizinine yerleştirilmiş bir AliPlayer lisans dosyası (license.crt).Projeye aktarılmış AUI Kits modülleri (
AUILiveRoomCore,AUILiveRoomViewer,AUIInteraction).Etkileşimli canlı yayın izleyicisi için izleyici belirteçleri veren bir AppServer uç noktası.
Sunucu tarafı demo: Toplu yükleme, kod dönüştürme ve oynatma
Aşağıdaki kod, bir kod dönüştürme şablon grubu ile toplu bir yükleme işi gönderir. Yükleme sırasında TemplateGroupId belirtmek, ayrı bir API çağrısı gerektirmeden otomatik kod dönüştürmeyi tetikler.
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.
HTTP geri arama hizmeti (temel mantık): Sunucu tarafı yeniden denemelerini önlemek için hemen HTTP 200 döndürür (S-7 kısıtlaması).
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']}")
Oynatma URL'sini alma (temel mantık):
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
Çalıştırma sonuçları
Toplu yüklemeyi gönderme:
$ 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
Geri arama hizmeti olayları alıyor:
$ 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=****
Aracı belge alımı
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
Temel tasarım kararları
Aşağıdaki tabloda, bu demo için temel tasarım kararları listelenmiş ve açık kısıtlama kimlikleri yapılandırılmış kısıtlama referansına kadar izlenmiştir.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
İstemci tarafı demo: Android oynatıcı ve canlı izleyici
Bu bölüm, sunucu tarafı iş akışının üzerine çalışan bir Android demosu oluşturur. Demo, minimum kodla bir MP4 dosyasını oynatır ve AUI Kits ile etkileşimli bir canlı yayın izleyicisini entegre eder.
Aracıya gönderilen istem:
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.
Aracı yürütme süreci
Aşama 1: İstemci tarafı llms dizinini okuma ve senaryoları eşleştirme
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)
Aşama 2: Detaylı belgeleri gerektiğinde yükleme
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Aşama 3: Temel kararları çıkarma
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.
Proje bağımlılıklarını ayarlama
Proje düzeyindeki build.gradle dosyasında:
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://maven.aliyun.com/nexus/content/repositories/releases" }
}
}
Uygulama düzeyindeki build.gradle dosyasında:
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'
}
İzinleri ve karartmayı yapılandırma
AndroidManifest.xml dosyasında:
<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 dosyasında:
-keep class com.alivc.**{*;}
-keep class com.aliyun.**{*;}
-keep class com.cicada.**{*;}
-dontwarn com.alivc.**
-dontwarn com.aliyun.**
-dontwarn com.cicada.**
Lisansı başlatma
SampleApp.java dosyasını oluşturun:
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);
}
}
AndroidManifest.xml dosyasında SampleApp kaydedin:
<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>
Tek video oynatma kullanıcı arayüzünü oluşturma
activity_player.xml düzen dosyasını oluşturun:
<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 dosyasını oluşturun:
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();
}
}
}
Günlüklerde prepared olayı ve ilk kare olayı görünürse ve SurfaceView görüntüyü doğru şekilde render ederse, alttaki bağlantı nettir.
AUI Kits canlı izleyiciyi entegre etme
AUI Kits modüllerini içe aktarma
settings.gradle dosyasında:
include ':app',
':AUILiveRoomCore',
':AUILiveRoomViewer',
':AUIInteraction'
Uygulama düzeyindeki build.gradle dosyasına aşağıdaki bağımlılıkları ekleyin:
implementation project(':AUILiveRoomCore')
implementation project(':AUILiveRoomViewer')
implementation project(':AUIInteraction')
AppServer işbirliği modeli
İstemci, hassas kimlik bilgilerini doğrudan tutmaz. Bunun yerine, AppServer kimlik doğrulamasından sonra bunları verir. Aşağıdaki diyagram, canlı bir odaya girme iş akışının tamamını göstermektedir:
[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)
Android uygulaması, oturum açma durumuyla birlikte AppServer'a bir
GET /api/v1/live/viewer/token?roomId=xxxisteği gönderir.AppServer, oturum açma durumunu doğrular ve
userId,nick,pullUrlveimsTokendeğerlerini verir.Uygulama
ViewerTokenInfoaldıktan sonra, canlı odaya girmek içinLiveRoomViewerActivity.start(params)çağrısını yapar.Dahili olarak AUI Kits, akış çekme için AliPlayer'ı ve canlı yorumlar (danmaku), beğeni ve hediye özellikleri için Etkileşimli Mesajlaşma Hizmeti'ne (IMS) bağlanmak için kullanır.
AppServerClient (OkHttp uygulaması)
AppServerClient.java ve ViewerTokenInfo.java dosyalarını oluşturun:
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
}
Demo girişlerini birleştirme
activity_main.xml düzen dosyasını oluşturun:
<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 dosyasını oluşturun:
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();
}
});
}
}
Doğrulama kontrol listesi
Demoyu çalıştırdıktan sonra aşağıdaki kullanıcı arayüzü davranışını ve günlük çıktısını doğrulayın:
Simple Playback seçeneğine tıklayın:
SimplePlayerActivitybaşlar ve video, siyah ekran olmadanSurfaceViewiçinde sorunsuz bir şekilde oynatılır.Interactive Live Streaming Viewer seçeneğine tıklayın: AUI Kits
LiveRoomViewerActivitybaşlatılır. AliPlayer, yayıncının video akışını görüntüler. Sağ alt köşedeki canlı yorumlar (danmaku), beğeni ve hediye panelleri çalışır durumdadır.Temel logcat günlükleri:
AliPlayer: prepared,AliPlayer: first frameveIMS: connectedifadelerinin aynı anda görünmesi, hem akış çekmenin hem de etkileşimin hazır olduğunu gösterir.
Aracı belge alımı
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
Temel tasarım kararları
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Lansman öncesi kontrol listesi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Son dizin yapısı
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
Sunucu tarafı ve istemci tarafı demoları eksiksiz, kapalı döngülü bir iş akışı oluşturur. llms.txt dizinini kullanarak Aracı; video yüklemeyi, otomatik kod dönüştürmeyi, oynatma URL'si almayı, temel video oynatmayı ve AUI Kits ile etkileşimli canlı yayın izlemeyi kapsar.
Ek: Aracı seçimi ve kendi kendine kontrol
Bu bölüm, Kodlama Aracısı yüklememiş geliştiriciler içindir.
Kodlama Aracısı ne zaman kullanılır
|
|
|
|
|
|
|
|
|
|
|
|
Önerilen seçenekler
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Kurulum bağlantıları için resmi ürün web sitesini kullanın. Üçüncü taraf görsellerden kaçının.
Minimum kendi kendine kontrol
Yeteneklerini doğrulamak için Kodlama Aracınıza aşağıdaki istemi gönderin:
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"?
Beklenen cevaplar:
llms.txtiçindeki üst düzey modülleri doğru şekilde listeler.Alt belgeleri, sunucu tarafı demosundaki ihtiyaç duyulduğunda yükleme tablosuyla büyük ölçüde tutarlı olacak şekilde listeler (medya yükleme, olay bildirimi, ses/video oynatma URL'si alma, Python SDK başlatma, medya işleme iş akışı).
Şunu açıkça belirtir: Alibaba Cloud hesabı AccessKey'i kullanmayın. Bunun yerine bir RAM kullanıcısı kullanın.
Üç kontrolün tamamından geçen bir aracı, yukarıdaki demolar için hazırdır.