「Unity/Agora/voicechat community/token取得」の版間の差分
(→本番tokenをワンタイムtoken経由で取得する) |
|||
(同じ利用者による、間の43版が非表示) | |||
行6: | 行6: | ||
==本番tokenをワンタイムtoken経由で取得する== | ==本番tokenをワンタイムtoken経由で取得する== | ||
− | # | + | #サンプルのClientManagerTestシーンだと、"VideoCanvas"のGameObjectとかに、TokenClientを、AddComponentする |
− | #ServerURLを入れる。(ttp://localhost:8080/ な感じ。この場合ttp://localhost:8080/rte/testing/publisher/uid/1234/? | + | #ServerURLを入れる。(ttp://localhost:8080/ な感じ。この場合ttp://localhost:8080/rte/testing/publisher/uid/1234/?3600 にアクセスされる) |
+ | #以下のようにRtcEngine.JoinChannel()部分をtoken取得コードに変更 | ||
− | == | + | ===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になるので、ドメインは、同じにする。 | ||
− | + | ==="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判定変数を追加 | |
+ | <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> | ||
− | == | + | ====パターン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 1日有効な本番token取得
- 2 本番tokenをワンタイムtoken経由で取得する
- 3 golangでワンタイムtokenを設定
- 4 phpでワンタイムtokenを取得する
- 5 serverURLを外部から入力できるように
- 6 Access-Control-Allow-Originエラーが出る場合
1日有効な本番token取得
- https://console.agora.io/ にアクセス
- stageをliveに
- Generate temp RTC tokenを選択して、チャンネル名を入れてtokenを取得
- サンプルのClientManagerTestシーンの、CanvasVideoのInspectorにあるuseTokenを、falseにして、token文字列を設置するとつながる
本番tokenをワンタイムtoken経由で取得する
- サンプルのClientManagerTestシーンだと、"VideoCanvas"のGameObjectとかに、TokenClientを、AddComponentする
- ServerURLを入れる。(ttp://localhost:8080/ な感じ。この場合ttp://localhost:8080/rte/testing/publisher/uid/1234/?3600 にアクセスされる)
- 以下のように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
- 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の取得方法は、以下の通り。
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");