日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

數(shù)字人流媒體開發(fā)指南

更新時(shí)間:

本文介紹數(shù)字人流媒體服務(wù)的接入流程和開發(fā)方案,以及示例代碼。

數(shù)字人流媒體服務(wù)(包括3D數(shù)字人流媒體服務(wù)和2D數(shù)字人流媒體服務(wù))是將數(shù)字人在云端渲染出的視頻畫面通過(guò)流媒體的方式輸出到客戶端,平臺(tái)目前提供了阿里云RTC流媒體渠道和標(biāo)準(zhǔn)RTMP流媒體渠道兩種渠道。播報(bào)數(shù)字人(對(duì)應(yīng)開放平臺(tái)的“咨詢播報(bào)”場(chǎng)景)和互動(dòng)數(shù)字人(對(duì)應(yīng)開放平臺(tái)的“客服助理”場(chǎng)景)使用阿里云RTC渠道,平臺(tái)會(huì)將數(shù)字人渲染的視頻流推到阿里云RTC服務(wù)器,客戶可以使用阿里云RTC的客戶端SDK進(jìn)行拉流播放對(duì)應(yīng)視頻流;推流數(shù)字人(對(duì)應(yīng)開放平臺(tái)的“虛擬主播”場(chǎng)景)使用標(biāo)準(zhǔn)RTMP渠道,平臺(tái)可以將數(shù)字人渲染的視頻流通過(guò)RTMP協(xié)議推流到支持對(duì)應(yīng)協(xié)議的直播平臺(tái),客戶可以從對(duì)應(yīng)的直播平臺(tái)觀看視頻流。

下面通過(guò)一個(gè)典型的客戶端-服務(wù)端架構(gòu)產(chǎn)品介紹數(shù)字人流媒體服務(wù)整體的接入流程。

1. 完整的技術(shù)鏈路圖

image
  • 整體架構(gòu)上分為客戶應(yīng)用、虛擬數(shù)字人開放平臺(tái)服務(wù)和阿里云RTC服務(wù)

  • 客戶應(yīng)用分為客戶端(包括:網(wǎng)頁(yè),小程序,APP等)和服務(wù)端(java服務(wù)器,python服務(wù)器等)

    • 如果客戶只有客戶端,如一個(gè)APP,沒(méi)有服務(wù)端的情況,目前平臺(tái)的服務(wù)端API使用的是阿里云的openapi,支持android直接調(diào)用(java sdk)

2. 核心鏈路介紹

2.1 啟動(dòng)數(shù)字人流媒體服務(wù)

  • 目的:

    • 啟動(dòng)一路數(shù)字人流媒體服務(wù),數(shù)字人的視頻畫面將被推送到阿里云RTC服務(wù)器(推流數(shù)字人是直接推流到對(duì)應(yīng)的直播平臺(tái))

  • 核心流程:

    • 客戶應(yīng)用客戶端向客戶應(yīng)用服務(wù)端發(fā)起啟動(dòng)數(shù)字人流媒體服務(wù)請(qǐng)求,客戶應(yīng)用服務(wù)端收到請(qǐng)求后通過(guò)調(diào)用虛擬數(shù)字人開放平臺(tái)服務(wù)端SDK的StartInstance接口啟動(dòng)一路數(shù)字人流媒體服務(wù)(目前平臺(tái)服務(wù)端SDK支持java/python/php三種開發(fā)語(yǔ)言,具體接入方案可參考服務(wù)端API接入。),拿到接口返回的sessionId和RTC流媒體服務(wù)參數(shù),然后返回給客戶應(yīng)用客戶端

2.2 拉取數(shù)字人視頻流

  • 目的:

    • 客戶端拉流對(duì)應(yīng)的數(shù)字人視頻流,并在客戶端進(jìn)行顯示

  • 核心流程:

    • 通過(guò)上一步服務(wù)端返回的RTC流媒體服務(wù)參數(shù),接入阿里云RTC客戶端SDK進(jìn)行拉流,目前阿里云RTC客戶端SDK支持全平臺(tái)接入(Android/IOS/Web/Windows等),接入方案可參考客戶端SDK接入

2.3 向數(shù)字人發(fā)送播報(bào)指令

  • 目的:

    • 驅(qū)動(dòng)數(shù)字人播報(bào)對(duì)應(yīng)的文本

  • 核心流程:

    • 客戶應(yīng)用客戶端向客戶應(yīng)用服務(wù)端發(fā)起驅(qū)動(dòng)數(shù)字人播報(bào)文本請(qǐng)求,客戶應(yīng)用服務(wù)端收到請(qǐng)求后通過(guò)調(diào)用虛擬數(shù)字人開放平臺(tái)服務(wù)端SDK的SendText接口驅(qū)動(dòng)數(shù)字人播報(bào),具體可參考文檔:數(shù)字人播報(bào)API接入指南

2.4 停止數(shù)字人流媒體服務(wù)

  • 目的:

    • 在使用完數(shù)字人流媒體服務(wù)之后停止對(duì)應(yīng)流媒體服務(wù),釋放資源(平臺(tái)根據(jù)數(shù)字人流媒體服務(wù)啟動(dòng)的數(shù)量進(jìn)行計(jì)費(fèi),請(qǐng)?jiān)谑褂猛瓿珊蠹皶r(shí)停止,避免造成無(wú)流媒體服務(wù)可用的情況)

  • 核心流程:

    • 客戶應(yīng)用客戶端向客戶應(yīng)用服務(wù)端發(fā)起停止數(shù)字人流媒體服務(wù)請(qǐng)求,客戶應(yīng)用服務(wù)端收到請(qǐng)求后通過(guò)調(diào)用虛擬數(shù)字人開放平臺(tái)服務(wù)端SDK的StopInstance接口停止數(shù)字人流媒體服務(wù)

3. 完整流媒體服務(wù)示例代碼

3.1 引入二方包

<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>avatar20220130</artifactId>
  <version>${使用最新版本}</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>${選擇一個(gè)合適版本}</version>
</dependency>

3.2 示例代碼

package com.aliyun.avatar.sample;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

import com.aliyun.avatar20220130.Client;
import com.aliyun.avatar20220130.models.SendCommandRequest;
import com.aliyun.avatar20220130.models.SendCommandResponse;
import com.aliyun.avatar20220130.models.SendCommandResponseBody;
import com.aliyun.avatar20220130.models.SendTextRequest;
import com.aliyun.avatar20220130.models.SendTextResponse;
import com.aliyun.avatar20220130.models.SendTextResponseBody;
import com.aliyun.avatar20220130.models.StartInstanceRequest;
import com.aliyun.avatar20220130.models.StartInstanceRequest.StartInstanceRequestApp;
import com.aliyun.avatar20220130.models.StartInstanceRequest.StartInstanceRequestUser;
import com.aliyun.avatar20220130.models.StartInstanceResponse;
import com.aliyun.avatar20220130.models.StartInstanceResponseBody;
import com.aliyun.avatar20220130.models.StartInstanceResponseBody.StartInstanceResponseBodyData;
import com.aliyun.avatar20220130.models.StartInstanceResponseBody.StartInstanceResponseBodyDataChannel;
import com.aliyun.avatar20220130.models.StopInstanceRequest;
import com.aliyun.avatar20220130.models.StopInstanceResponse;
import com.aliyun.avatar20220130.models.StopInstanceResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;

/**
 * <pre>
 *     avatar sample
 * </pre>
 *
 */
public class AvatarOnlineSample {
    private Client client;

    /**
     * 初始化
     *
     * @throws Exception
     */
    public void init() throws Exception {
        // 請(qǐng)確保代碼運(yùn)行環(huán)境設(shè)置了環(huán)境變量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        // 工程代碼泄露可能會(huì)導(dǎo)致 AccessKey 泄露,并威脅賬號(hào)下所有資源的安全性。以下代碼示例使用環(huán)境變量獲取 AccessKey 的方式進(jìn)行調(diào)用,僅供參考,建議使用更安全的 STS 方式,更多鑒權(quán)訪問(wèn)方式請(qǐng)參見:http://bestwisewords.com/document_detail/378657.html
        String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
        client = createClient(accessKeyId, accessKeySecret);
    }

    /**
     * 使用AK&SK初始化賬號(hào)Client
     *
     * @param accessKeyId
     * @param accessKeySecret
     * @return Client
     * @throws Exception
     */
    public Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        Config config = new Config()
            // 必填,您的 AccessKey ID
            .setAccessKeyId(accessKeyId)
            // 必填,您的 AccessKey Secret
            .setAccessKeySecret(accessKeySecret);
        // 訪問(wèn)的域名
        config.endpoint = "avatar.cn-zhangjiakou.aliyuncs.com";
        return new Client(config);
    }

    /**
     * 啟動(dòng)一路數(shù)據(jù)流媒體服務(wù)
     *
     * @param tenantId
     * @param appId
     */
    public StartInstanceResponseBodyData startInstance(Long tenantId, String appId) throws Exception {
        StartInstanceRequestUser user = new StartInstanceRequestUser();
        user.setUserId("avatar_sample_userId");
        user.setUserName("avatar_sample_userName");

        StartInstanceRequestApp app = new StartInstanceRequestApp();
        app.setAppId(appId);

        StartInstanceRequest request = new StartInstanceRequest();
        request.setTenantId(tenantId);
        request.setApp(app);
        request.setUser(user);
        RuntimeOptions runtime = new RuntimeOptions();
        StartInstanceResponse response = client.startInstanceWithOptions(request, runtime);
        StartInstanceResponseBody responseBody = response.getBody();
        if (null != responseBody.getSuccess() && responseBody.getSuccess()) {
            // 調(diào)用成功
            System.out.println("啟動(dòng)成功,sessionId:" + responseBody.getData().getSessionId());
            return responseBody.getData();
        } else {
            // 調(diào)用失敗
            System.out.println("啟動(dòng)失敗,原因:" + responseBody.getCode() + ":" + responseBody.getMessage());
            throw new Exception("啟動(dòng)失敗");
        }
    }

    /**
     * 停止一路數(shù)據(jù)流媒體服務(wù)
     *
     * @param tenantId
     * @param sessionId
     */
    public void stopInstance(Long tenantId, String sessionId) throws Exception {
        StopInstanceRequest request = new StopInstanceRequest();
        request.setTenantId(tenantId);
        request.setSessionId(sessionId);
        RuntimeOptions runtime = new RuntimeOptions();
        StopInstanceResponse response = client.stopInstanceWithOptions(request, runtime);
        StopInstanceResponseBody responseBody = response.getBody();
        if (null != responseBody.getSuccess() && responseBody.getSuccess()) {
            // 調(diào)用成功
            System.out.println("停止成功,sessionId:" + responseBody.getData().getSessionId());
        } else {
            // 調(diào)用失敗
            System.out.println("停止失敗,原因:" + responseBody.getCode() + ":" + responseBody.getMessage());
            throw new Exception("停止失敗");
        }
    }

    /**
     * 發(fā)送文本消息
     *
     * @param tenantId
     * @param sessionId
     * @param text
     */
    public void sendText(Long tenantId, String sessionId, String text) throws Exception {
        System.out.println(formatCurrentTime() + ":開始發(fā)送文本消息:" + text);
        SendTextRequest request = new SendTextRequest();
        request.setTenantId(tenantId);
        request.setSessionId(sessionId);
        // 本次播報(bào)是否打斷當(dāng)前數(shù)字人正在播報(bào)的內(nèi)容
        // true表示打斷,false的話會(huì)等待當(dāng)前數(shù)字人正在播報(bào)的內(nèi)容結(jié)束才會(huì)播報(bào)本次播報(bào)內(nèi)容
        request.setInterrupt(true);
        request.setText(text);
        request.setUniqueCode(UUID.randomUUID().toString());
        RuntimeOptions runtime = new RuntimeOptions();
        SendTextResponse response = client.sendTextWithOptions(request, runtime);
        SendTextResponseBody responseBody = response.getBody();
        if (null != responseBody.getSuccess() && responseBody.getSuccess()) {
            // 調(diào)用成功
            System.out.println(formatCurrentTime() + ":發(fā)送文本消息成功, unqieCode: " + request.getUniqueCode());
        } else {
            // 調(diào)用失敗
            System.out.println("發(fā)送文本消息失敗,原因:" + responseBody.getCode() + ":" + responseBody.getMessage());
            throw new Exception("發(fā)送文本消息失敗");
        }
    }

    /**
     * 發(fā)送指令消息
     *
     * @param tenantId
     * @param sessionId
     * @param code
     * @param content
     */
    public void sendCommand(Long tenantId, String sessionId, String code, Map<String, Object> content)
        throws Exception {
        SendCommandRequest request = new SendCommandRequest();
        request.setTenantId(tenantId);
        request.setSessionId(sessionId);
        request.setCode(code);
        request.setContent(content);
        request.setUniqueCode(UUID.randomUUID().toString());
        RuntimeOptions runtime = new RuntimeOptions();
        SendCommandResponse response = client.sendCommandWithOptions(request, runtime);
        SendCommandResponseBody responseBody = response.getBody();
        if (null != responseBody.getSuccess() && responseBody.getSuccess()) {
            // 調(diào)用成功
            System.out.println(formatCurrentTime() + ":發(fā)送指令消息成功");
        } else {
            // 調(diào)用失敗
            System.out.println("發(fā)送指令消息失敗,原因:" + responseBody.getCode() + ":" + responseBody.getMessage());
            throw new Exception("發(fā)送指令消息失敗");
        }
    }

    public static void main(String[] args) throws Exception {
        // 開發(fā)者信息定義,獲取方式參考文檔:http://bestwisewords.com/document_detail/479093.html
        Long tenantId = null;
        String appId = null;
        AvatarOnlineSample sample = new AvatarOnlineSample();
        // 1. 初始化
        sample.init();

        // 2. 啟動(dòng)一路數(shù)字人流媒體服務(wù)
        StartInstanceResponseBodyData response = sample.startInstance(tenantId, appId);
        // 2.1 獲取啟動(dòng)成功的sessionId
        String sessionId = response.getSessionId();
        // 2.2 獲取對(duì)應(yīng)的channel信息用于客戶端拉流,可以使用平臺(tái)提供的測(cè)試頁(yè)面快速體驗(yàn):http://bestwisewords.com/document_detail/392352.html
        StartInstanceResponseBodyDataChannel channel = response.getChannel();
        System.out.println(JSONObject.toJSONString(channel, SerializerFeature.PrettyFormat));
        // 2.3 示例代碼這里sleep,可以去平臺(tái)的測(cè)試頁(yè)面拉流查看是否成功
        Thread.sleep(60000);

        // 3. 發(fā)送消息驅(qū)動(dòng)數(shù)字人播報(bào),詳細(xì)可參考文檔:http://bestwisewords.com/document_detail/478895.html
        // 3.1 發(fā)送一條測(cè)試文本消息
        //     發(fā)送之后數(shù)字人會(huì)進(jìn)行播報(bào),示例代碼通過(guò)sleep模擬等待數(shù)字人播報(bào),實(shí)際可根據(jù)業(yè)務(wù)情況發(fā)送下一條播報(bào)
        sample.sendText(tenantId, sessionId, formatCurrentTime() + ",我是虛擬數(shù)字人,這是一段示例代碼,我正在播報(bào)一條示例文本");
        Thread.sleep(15000);
        // 3.2 發(fā)送一條測(cè)試文本消息,自定義數(shù)字人動(dòng)作,詳細(xì)可參考文檔:http://bestwisewords.com/document_detail/478895.html
        //     注意:實(shí)際測(cè)試的時(shí)候可能會(huì)因?yàn)槭褂玫臄?shù)字人不同以及行業(yè)不同,導(dǎo)致下面的自定義動(dòng)作不生效
        sample.sendText(tenantId, sessionId, "<speak>" + formatCurrentTime() + ",大家好<vh-action code=\"animation_4960\" interrupt=\"true\"/>,這是一段虛擬數(shù)字人播報(bào)測(cè)試文本,歡迎大家! </speak>");
        Thread.sleep(15000);
        // 3.3 發(fā)送一條測(cè)試指令消息,目前指令只支持打斷數(shù)字人播報(bào)
        sample.sendText(tenantId, sessionId, formatCurrentTime() + ",虛擬數(shù)字人是一項(xiàng)整合了語(yǔ)音、圖像、3D美術(shù)、自然語(yǔ)言處理等多領(lǐng)域綜合且復(fù)雜的技術(shù)。阿里云虛擬數(shù)字人開放平臺(tái),依托阿里達(dá)摩院強(qiáng)大的AI技術(shù)能力,為阿里云客戶提供了低門檻、輕量級(jí)、易集成的3D數(shù)字人、2D數(shù)字人實(shí)時(shí)和離線驅(qū)動(dòng)能力,讓阿里云客戶能夠輕松的將數(shù)字人能力接入到自己的業(yè)務(wù)中,從而體驗(yàn)到數(shù)字人技術(shù)帶來(lái)的業(yè)務(wù)提升;同時(shí)平臺(tái)還提供了豐富的數(shù)字人資產(chǎn)形象庫(kù),以及為了方便非開發(fā)人員使用和體驗(yàn)還提供了完善的數(shù)字人視頻創(chuàng)作SAAS產(chǎn)品。");
        Thread.sleep(5000);
        sample.sendCommand(tenantId, sessionId, "INTERRUPT", null);
        Thread.sleep(3000);

        // 4. 停止數(shù)字人流媒體服務(wù),釋放資源
        sample.stopInstance(tenantId, sessionId);
    }

    private static String formatCurrentTime() {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss,SSS");
        return format.format(new Date());
    }
}

以上就是一個(gè)典型的客戶端-服務(wù)端架構(gòu)產(chǎn)品使用數(shù)字人流媒體服務(wù)的整體鏈路,關(guān)于播報(bào)數(shù)字人、互動(dòng)數(shù)字人等具體數(shù)字人流媒體服務(wù)的接入可參考下方詳細(xì)的接入指南: