facebook twitter hatena line email

「Unity/Agora/voicechat community/token取得」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
(本番tokenをワンタイムtoken経由で取得する)
 
(同じ利用者による、間の42版が非表示)
行6: 行6:
  
 
==本番tokenをワンタイムtoken経由で取得する==
 
==本番tokenをワンタイムtoken経由で取得する==
#VideoCanvasのオブジェクトとかに、ClientTokenを検索してAddComponentする
+
#サンプルのClientManagerTestシーンだと、"VideoCanvas"のGameObjectとかに、TokenClientを、AddComponentする
 
#ServerURLを入れる。(ttp://localhost:8080/ な感じ。この場合ttp://localhost:8080/rte/testing/publisher/uid/1234/?3600 にアクセスされる)
 
#ServerURLを入れる。(ttp://localhost:8080/ な感じ。この場合ttp://localhost:8080/rte/testing/publisher/uid/1234/?3600 にアクセスされる)
 +
#以下のようにRtcEngine.JoinChannel()部分をtoken取得コードに変更
  
==useTokenをtrueにすることでエラーになる==
+
===mRtcEngine.JoinChannel()部分をtoken取得コードに変更===
 +
<pre>
 +
string token = "";
 +
if (!useToken)
 +
{
 +
    mRtcEngine.JoinChannel(token, CHANNEL_NAME_1, "", 0, new ChannelMediaOptions(true, true, true, true));
 +
}
 +
else
 +
{
 +
    TokenClient.Instance.SetRtcEngineInstance(mRtcEngine);
 +
    TokenClient.Instance.GetRtcToken(CHANNEL_NAME_1, 0, (token) =>
 +
    {
 +
        mRtcEngine.JoinChannel(token, CHANNEL_NAME_1, "", 0, new ChannelMediaOptions(true, true, true, true));
 +
    });
 +
}
 +
</pre>
 +
====別チャンネルを作ってる場合====
 +
チャンネル名(例:"CHANNEL_NAME_VIDEO")をあわせる。
 +
channelVideo = mRtcEngine.CreateChannel(CHANNEL_NAME_VIDEO);
 +
<pre>
 +
if (!useToken)
 +
{
 +
    channelVideo.JoinChannel(token, "", 0, new ChannelMediaOptions(true, true));
 +
}
 +
else
 +
{
 +
    TokenClient.Instance.SetRtcEngineInstance(mRtcEngine);
 +
    TokenClient.Instance.GetRtcToken(CHANNEL_NAME_VIDEO, 0, (token) =>
 +
    {
 +
        channelVideo.JoinChannel(token, "", 0, new ChannelMediaOptions(true, true));
 +
    });
 +
}
 +
</pre>
 +
 
 +
===useTokenをtrueにすることでエラーになる場合===
 
<pre>
 
<pre>
 
ArgumentNullException: String reference not set to an instance of a String.
 
ArgumentNullException: String reference not set to an instance of a String.
 
Parameter name: source
 
Parameter name: source
 
</pre>
 
</pre>
 +
TokenClientを、どこかのGameObjectにAddComponentしてServerURLを設定すれば良い。
 +
===token文字列が取得できない場合===
 +
token取得用apiと、unity設置してるサイトのドメインが同じでない場合は、network.errorになるので、ドメインは、同じにする。
  
GetRtcToken()内の以下場所で、serverURLが、nullなので、エラーが出てるっぽい。
+
==="audience can not publish stream"エラーとなる場合===
if (!serverURL.StartsWith("http"))
+
エラー詳細
 +
Uncaught (in promise) AgoraRTCException: AgoraRTCError INVALID_OPERATION: audience can not publish stream
 +
*JoinChannel()前に、SetClientRole()を実行してないため起こる。JoinChannel()前に、SetClientRole()を実行すれば良い。
 +
*StopScreenShare()の際に起こる場合は、SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_AUDIENCE);の実行を遅らせるなど
  
==serverURLを入れる必要がありそう==
+
==="renewToken should not be called before user join"エラーとなる場合===
    ///    The helper class gets the token from a server endpoint conformed to
+
エラー詳細
     /// format like this:
+
AgoraRTCException: AgoraRTCError INVALID_OPERATION: renewToken should not be called before user join
     ///  http://localhost:8080/rte/testing/publisher/uid/1234/?3600
+
参加前にrenewTokenを使ってるためで、対応方法を2パターン
     /// See the GitHub project for compatible server code in GoLang:
+
====パターン1====
     ///  https://github.com/AgoraIO-Community/agora-token-service
+
TokenClient.csのOnClientRoleChangedHandlerメソッド内の以下ChannelNameをpublicにし、joined判定変数を追加
 +
<pre>
 +
- string ChannelName { get; set; }
 +
+ public string ChannelName { get; set; }
 +
+ bool joined = false;
 +
</pre>
 +
SetRtcEngineInstanceに以下を追加
 +
<pre>
 +
public void SetRtcEngineInstance(IRtcEngine engine)
 +
{
 +
     mRtcEngine = engine;
 +
    mRtcEngine.OnTokenPrivilegeWillExpire = OnTokenPrivilegeWillExpireHandler;
 +
    mRtcEngine.OnTokenPrivilegeDidExpire = OnTokenPrivilegeDidExpireHandler;
 +
    mRtcEngine.OnClientRoleChanged += OnClientRoleChangedHandler;
 +
+    mRtcEngine.OnJoinChannelSuccess += OnJoinChannelSuccess;
 +
+    mRtcEngine.OnLeaveChannel += OnLeaveChannel;
 +
}
 +
</pre>
 +
OnClientRoleChangedHandlerに以下のStartCoroutine(TokenRequestHelper.FetchRtcToken(〜にjoined判定を追加
 +
<pre>
 +
void OnClientRoleChangedHandler(CLIENT_ROLE_TYPE oldRole, CLIENT_ROLE_TYPE newRole)
 +
{
 +
    clientType = newRole == CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER ? ClientType.publisher : ClientType.subscriber;
 +
     Debug.Log("Client Token will change for " + ChannelName + ", renewing from " + oldRole + " to " + newRole);
 +
+    if (joined)
 +
+    {
 +
        StartCoroutine(TokenRequestHelper.FetchRtcToken(serverURL, ChannelName, UID, clientType.ToString(), ExpirationSecs, this.RenewToken));
 +
+    }
 +
}
 +
</pre>
 +
OnJoinChannelSuccessとOnLeaveChannelメソッドを追加
 +
<pre>
 +
void OnJoinChannelSuccess(string channelName, uint uid, int elapsed)
 +
{
 +
     Debug.LogFormat("TokenClient.OnJoinChannelSuccess JoinChannel={0} Success: uid ", channelName, uid);
 +
     joined = true;
 +
}
 +
void OnLeaveChannel(RtcStats stats)
 +
{
 +
    Debug.LogFormat("TokenClient.OnLeaveChannel duration={0} txVideoBytes:{1} ", stats.duration, stats.txVideoBytes);
 +
    joined = false;
 +
}
 +
</pre>
 +
SetRtcEngineInstanceの接続前に、"TokenClient.Instance.ChannelName = channel;"を追加
 +
<pre>
 +
if (!useToken)
 +
{
 +
    mRtcEngine.JoinChannel(token, channel, "", 0, new ChannelMediaOptions(true, false, true, false));
 +
}
 +
else
 +
{
 +
+    TokenClient.Instance.ChannelName = channel;
 +
    TokenClient.Instance.SetRtcEngineInstance(mRtcEngine);
 +
    TokenClient.Instance.GetRtcToken(channel, 0, (token) =>
 +
    {
 +
        mRtcEngine.JoinChannel(token, channel, "", 0, new ChannelMediaOptions(true, false, true, false));
 +
    });
 +
}
 +
</pre>
  
==goのtokenを設定==
+
====パターン2====
 +
TokenClient.csのOnClientRoleChangedHandlerメソッド内の以下を、コメントアウトすれば、とりあえず、つながる。
 +
<pre>
 +
// 以下が有ると、useToken時に、join前に、実行されてしまい、ChannelNameが空で、エラーとなり接続が止まるので、コメントアウト。問題あれば、再度考える
 +
StartCoroutine(TokenRequestHelper.FetchRtcToken(serverURL, ChannelName, UID, clientType.ToString(), ExpirationSecs, this.RenewToken));
 +
</pre>
 +
 
 +
==="Cannot read properties of undefined"エラーとなる場合===
 +
エラー詳細
 +
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'toString')
 +
本番のAppIDで、useTokenを、falseにしてると、このようなエラーが出るので、AppIdをテスト用に。
 +
 
 +
==golangでワンタイムtokenを設定==
 
https://github.com/AgoraIO-Community/agora-token-service
 
https://github.com/AgoraIO-Community/agora-token-service
 
===agora-token-service設定===
 
===agora-token-service設定===
行36: 行147:
 
</pre>
 
</pre>
 
  $ go run cmd/main.go
 
  $ go run cmd/main.go
 +
 +
==phpでワンタイムtokenを取得する==
 +
$ git clone https://github.com/AgoraIO/Tools.git
 +
#agora-token/Tools/DynamicKey/AgoraDynamicKey/php をサーバーへ設置する。
 +
#RtcTokenBuilderSample.phpを確認する
 +
#serverURLにttp://localhost:8080/php/sample/RtcTokenBuilderSample.php?を設置する
 +
#処理すると、ttp://localhost:8080/php/sample/RtcTokenBuilderSample.php?/rtc/unity3d/publisher/uid/0/?expiry=3600 が実行される。
 +
#このときrtcとuidの取得方法は、以下の通り。
 +
<pre>
 +
if (preg_match("!/rtc/([\d\w]+)!", $_SERVER['QUERY_STRING'], $matches)) {
 +
    $channelName = $matches[1];
 +
}
 +
if (preg_match("!/uid/([\d\w]+)!", $_SERVER['QUERY_STRING'], $matches)) {
 +
    $uid = $matches[1];
 +
    $uidStr = $matches[1];
 +
}
 +
if (preg_match("!/publisher/!", $_SERVER['QUERY_STRING'], $matches)) {
 +
    $role = RtcTokenBuilder::RolePublisher;
 +
} else if (preg_match("!/subscriber/!", $_SERVER['QUERY_STRING'], $matches)) {
 +
    $role = RtcTokenBuilder::RoleSubscriber;
 +
}
 +
</pre>
 +
戻り値はjsonで
 +
<pre>
 +
echo json_encode(array('rtcToken' => $token, 'rtmToken' => $token));
 +
</pre>
 +
==="CAN_NOT_GET_GATEWAY_SERVER"エラーとなる場合===
 +
エラー詳細
 +
Agora-SDK [ERROR]: [client-1513c] join number: 1, Joining channel failed, rollback AgoraRTCException: AgoraRTCError CAN_NOT_GET_GATEWAY_SERVER: flag: 4096, message: AgoraRTCError CAN_NOT_GET_GATEWAY_SERVER: invalid token, authorized failed
 +
*AccessToken2Sample.phpではなく、RtcTokenBuilderSample.phpの方を使う。
 +
*token文字列がおかしいので、channelNameがちゃんと設定されてるか確認する。
 +
*本番用Appなのに、tokenを使わなかった場合はこのエラーが出る。テスト用AppIdに切り替えるか、本番のAppIdでToken取得を使うように。
 +
 +
===接続できないとき確認===
 +
*AppIdが正しいか。tokenをonにしてるのに、AppIdがテスト用になってないかとか。
 +
 +
==serverURLを外部から入力できるように==
 +
TokenClient.csに以下を追加
 +
public string ServerURL { set => serverURL = value; }
 +
TokenClient.csの以下Start()メソッドは削除。これがあるとIsInitializedがfalseのままになってしまう。
 +
<pre>
 +
void Start()
 +
{
 +
    if (!serverURL.StartsWith("http"))
 +
    {
 +
      Debug.LogWarning("Please specify server URL in the " + gameObject.name + " gameobject, if you wish to use token server.");
 +
      return;
 +
    }
 +
    IsInitialized = true;
 +
}
 +
</pre>
 +
以下のCoGetTokens内のIsInitializedをserverURL.StartsWith("http")に変更。
 +
<pre>
 +
IEnumerator CoGetTokens(string channelName, uint uid, OnSingleTokenReceivedHandler handleToken)
 +
        {
 +
-            yield return new WaitUntil(() => IsInitialized);
 +
+            yield return new WaitUntil(() => (serverURL.StartsWith("http")));
 +
</pre>
 +
 +
==Access-Control-Allow-Originエラーが出る場合==
 +
エラー詳細
 +
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
 +
phpであれば
 +
<pre>
 +
header("Access-Control-Allow-Origin: *");
 +
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
 +
header("Access-Control-Allow-Headers: Content-Disposition, Content-Type, Content-Length, Accept-Encoding");
 +
header("Content-type:application/json");
 +
</pre>

2023年2月19日 (日) 09:49時点における最新版

1日有効な本番token取得

  1. https://console.agora.io/ にアクセス
  2. stageをliveに
  3. Generate temp RTC tokenを選択して、チャンネル名を入れてtokenを取得
  4. サンプルのClientManagerTestシーンの、CanvasVideoのInspectorにあるuseTokenを、falseにして、token文字列を設置するとつながる

本番tokenをワンタイムtoken経由で取得する

  1. サンプルのClientManagerTestシーンだと、"VideoCanvas"のGameObjectとかに、TokenClientを、AddComponentする
  2. ServerURLを入れる。(ttp://localhost:8080/ な感じ。この場合ttp://localhost:8080/rte/testing/publisher/uid/1234/?3600 にアクセスされる)
  3. 以下のようにRtcEngine.JoinChannel()部分をtoken取得コードに変更

mRtcEngine.JoinChannel()部分をtoken取得コードに変更

string token = "";
if (!useToken)
{
    mRtcEngine.JoinChannel(token, CHANNEL_NAME_1, "", 0, new ChannelMediaOptions(true, true, true, true));
}
else
{
    TokenClient.Instance.SetRtcEngineInstance(mRtcEngine);
    TokenClient.Instance.GetRtcToken(CHANNEL_NAME_1, 0, (token) =>
    {
        mRtcEngine.JoinChannel(token, CHANNEL_NAME_1, "", 0, new ChannelMediaOptions(true, true, true, true));
    });
}

別チャンネルを作ってる場合

チャンネル名(例:"CHANNEL_NAME_VIDEO")をあわせる。

channelVideo = mRtcEngine.CreateChannel(CHANNEL_NAME_VIDEO);
if (!useToken)
{
    channelVideo.JoinChannel(token, "", 0, new ChannelMediaOptions(true, true));
}
else
{
    TokenClient.Instance.SetRtcEngineInstance(mRtcEngine);
    TokenClient.Instance.GetRtcToken(CHANNEL_NAME_VIDEO, 0, (token) =>
    {
        channelVideo.JoinChannel(token, "", 0, new ChannelMediaOptions(true, true));
    });
}

useTokenをtrueにすることでエラーになる場合

ArgumentNullException: String reference not set to an instance of a String.
Parameter name: source

TokenClientを、どこかのGameObjectにAddComponentしてServerURLを設定すれば良い。

token文字列が取得できない場合

token取得用apiと、unity設置してるサイトのドメインが同じでない場合は、network.errorになるので、ドメインは、同じにする。

"audience can not publish stream"エラーとなる場合

エラー詳細

Uncaught (in promise) AgoraRTCException: AgoraRTCError INVALID_OPERATION: audience can not publish stream
  • JoinChannel()前に、SetClientRole()を実行してないため起こる。JoinChannel()前に、SetClientRole()を実行すれば良い。
  • StopScreenShare()の際に起こる場合は、SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_AUDIENCE);の実行を遅らせるなど

"renewToken should not be called before user join"エラーとなる場合

エラー詳細

AgoraRTCException: AgoraRTCError INVALID_OPERATION: renewToken should not be called before user join

参加前にrenewTokenを使ってるためで、対応方法を2パターン

パターン1

TokenClient.csのOnClientRoleChangedHandlerメソッド内の以下ChannelNameをpublicにし、joined判定変数を追加

- string ChannelName { get; set; }
+ public string ChannelName { get; set; }
+ bool joined = false;

SetRtcEngineInstanceに以下を追加

public void SetRtcEngineInstance(IRtcEngine engine)
{
    mRtcEngine = engine;
    mRtcEngine.OnTokenPrivilegeWillExpire = OnTokenPrivilegeWillExpireHandler;
    mRtcEngine.OnTokenPrivilegeDidExpire = OnTokenPrivilegeDidExpireHandler;
    mRtcEngine.OnClientRoleChanged += OnClientRoleChangedHandler;
+    mRtcEngine.OnJoinChannelSuccess += OnJoinChannelSuccess;
+    mRtcEngine.OnLeaveChannel += OnLeaveChannel;
}

OnClientRoleChangedHandlerに以下のStartCoroutine(TokenRequestHelper.FetchRtcToken(〜にjoined判定を追加

void OnClientRoleChangedHandler(CLIENT_ROLE_TYPE oldRole, CLIENT_ROLE_TYPE newRole)
{
    clientType = newRole == CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER ? ClientType.publisher : ClientType.subscriber;
    Debug.Log("Client Token will change for " + ChannelName + ", renewing from " + oldRole + " to " + newRole);
+    if (joined)
+    {
        StartCoroutine(TokenRequestHelper.FetchRtcToken(serverURL, ChannelName, UID, clientType.ToString(), ExpirationSecs, this.RenewToken));
+    }
}

OnJoinChannelSuccessとOnLeaveChannelメソッドを追加

void OnJoinChannelSuccess(string channelName, uint uid, int elapsed)
{
    Debug.LogFormat("TokenClient.OnJoinChannelSuccess JoinChannel={0} Success: uid ", channelName, uid);
    joined = true;
}
void OnLeaveChannel(RtcStats stats)
{
    Debug.LogFormat("TokenClient.OnLeaveChannel duration={0} txVideoBytes:{1} ", stats.duration, stats.txVideoBytes);
    joined = false;
}

SetRtcEngineInstanceの接続前に、"TokenClient.Instance.ChannelName = channel;"を追加

if (!useToken)
{
    mRtcEngine.JoinChannel(token, channel, "", 0, new ChannelMediaOptions(true, false, true, false));
}
else
{
+    TokenClient.Instance.ChannelName = channel;
    TokenClient.Instance.SetRtcEngineInstance(mRtcEngine);
    TokenClient.Instance.GetRtcToken(channel, 0, (token) =>
    {
        mRtcEngine.JoinChannel(token, channel, "", 0, new ChannelMediaOptions(true, false, true, false));
    });
}

パターン2

TokenClient.csのOnClientRoleChangedHandlerメソッド内の以下を、コメントアウトすれば、とりあえず、つながる。

// 以下が有ると、useToken時に、join前に、実行されてしまい、ChannelNameが空で、エラーとなり接続が止まるので、コメントアウト。問題あれば、再度考える
StartCoroutine(TokenRequestHelper.FetchRtcToken(serverURL, ChannelName, UID, clientType.ToString(), ExpirationSecs, this.RenewToken));

"Cannot read properties of undefined"エラーとなる場合

エラー詳細

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'toString')

本番のAppIDで、useTokenを、falseにしてると、このようなエラーが出るので、AppIdをテスト用に。

golangでワンタイムtokenを設定

https://github.com/AgoraIO-Community/agora-token-service

agora-token-service設定

$ git clone https://github.com/AgoraIO-Community/agora-token-service.git
$ cp .env.example .env

.envを設定

APP_ID=
APP_CERTIFICATE=
$ go run cmd/main.go

phpでワンタイムtokenを取得する

$ git clone https://github.com/AgoraIO/Tools.git
  1. agora-token/Tools/DynamicKey/AgoraDynamicKey/php をサーバーへ設置する。
  2. RtcTokenBuilderSample.phpを確認する
  3. serverURLにttp://localhost:8080/php/sample/RtcTokenBuilderSample.php?を設置する
  4. 処理すると、ttp://localhost:8080/php/sample/RtcTokenBuilderSample.php?/rtc/unity3d/publisher/uid/0/?expiry=3600 が実行される。
  5. このときrtcとuidの取得方法は、以下の通り。
if (preg_match("!/rtc/([\d\w]+)!", $_SERVER['QUERY_STRING'], $matches)) {
    $channelName = $matches[1];
}
if (preg_match("!/uid/([\d\w]+)!", $_SERVER['QUERY_STRING'], $matches)) {
    $uid = $matches[1];
    $uidStr = $matches[1];
}
if (preg_match("!/publisher/!", $_SERVER['QUERY_STRING'], $matches)) {
    $role = RtcTokenBuilder::RolePublisher;
} else if (preg_match("!/subscriber/!", $_SERVER['QUERY_STRING'], $matches)) {
    $role = RtcTokenBuilder::RoleSubscriber;
}

戻り値はjsonで

echo json_encode(array('rtcToken' => $token, 'rtmToken' => $token));

"CAN_NOT_GET_GATEWAY_SERVER"エラーとなる場合

エラー詳細

Agora-SDK [ERROR]: [client-1513c] join number: 1, Joining channel failed, rollback AgoraRTCException: AgoraRTCError CAN_NOT_GET_GATEWAY_SERVER: flag: 4096, message: AgoraRTCError CAN_NOT_GET_GATEWAY_SERVER: invalid token, authorized failed
  • AccessToken2Sample.phpではなく、RtcTokenBuilderSample.phpの方を使う。
  • token文字列がおかしいので、channelNameがちゃんと設定されてるか確認する。
  • 本番用Appなのに、tokenを使わなかった場合はこのエラーが出る。テスト用AppIdに切り替えるか、本番のAppIdでToken取得を使うように。

接続できないとき確認

  • AppIdが正しいか。tokenをonにしてるのに、AppIdがテスト用になってないかとか。

serverURLを外部から入力できるように

TokenClient.csに以下を追加

public string ServerURL { set => serverURL = value; }

TokenClient.csの以下Start()メソッドは削除。これがあるとIsInitializedがfalseのままになってしまう。

void Start()
{
    if (!serverURL.StartsWith("http"))
    {
      Debug.LogWarning("Please specify server URL in the " + gameObject.name + " gameobject, if you wish to use token server.");
      return;
    }
    IsInitialized = true;
}

以下のCoGetTokens内のIsInitializedをserverURL.StartsWith("http")に変更。

IEnumerator CoGetTokens(string channelName, uint uid, OnSingleTokenReceivedHandler handleToken)
         {
-            yield return new WaitUntil(() => IsInitialized);
+            yield return new WaitUntil(() => (serverURL.StartsWith("http")));

Access-Control-Allow-Originエラーが出る場合

エラー詳細

has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

phpであれば

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Disposition, Content-Type, Content-Length, Accept-Encoding");
header("Content-type:application/json");