Allmine API
Live Stream

Agora RTM token — mobil ve web

RTM token alma ve yenileme entegrasyonu

Agora RTM Token - Mobile/Web Integration

Migration rehberi

Yapılandırma sırası için Migration şablonu. Yeni düzenlemelerde Amaç → Önkoşullar → Endpoint → Request/Response → Hata kodları → Client adımları → İlgili sayfalar bölümlerini tercih edin.

Bu doküman, mobil ve web istemcilerinin canlı yayın join response'undan Agora RTM token alıp agora-rtm-sdk ile login olması için gereken minimum entegrasyon bilgisini verir.

Kapsam

  • Ayrı RTM token endpoint'i yoktur.
  • RTM token sadece mevcut live stream join endpoint'leriyle döner.
  • Frontend tarafında token üretilmez.
  • App Certificate veya secret hiçbir client build'ine konmaz.
  • POST /api/v1/live-stream/create RTM token dönmez. Yayın sahibi yayına girmek için join-as-creator çağırdığında RTM token alır.

Endpointler

Auth tüm endpointlerde zorunludur:

Authorization: Bearer <JWT>

Audience:

POST /api/v1/live-stream/join
Content-Type: application/json

{
  "liveStreamId": "65f000000000000000000001",
  "role": "audience"
}

Creator:

POST /api/v1/live-stream/join-as-creator
Content-Type: application/json

{
  "liveStreamId": "65f000000000000000000001"
}

Guest:

POST /api/v1/live-stream/join-as-guest
Content-Type: application/json

{
  "liveStreamId": "65f000000000000000000001"
}

Response

Backend standart response wrapper döner. İstemcinin kullanacağı alanlar data içindedir.

{
  "isSuccess": true,
  "statusCode": 201,
  "data": {
    "liveStream": {
      "id": "65f000000000000000000001",
      "channelName": "stream-channel"
    },
    "agora": {
      "appId": "agora-app-id",
      "channelName": "stream-channel",
      "token": "rtc-token",
      "uid": 123456,
      "role": "audience",
      "expiresAt": "2026-05-20T13:00:00.000Z"
    },
    "rtm": {
      "appId": "agora-app-id",
      "channelName": "stream-channel",
      "userId": "65f000000000000000000002",
      "token": "rtm-token",
      "expiresAt": "2026-05-20T13:00:00.000Z"
    }
  },
  "errors": [],
  "timestamp": "2026-05-20T12:00:00.000Z"
}

Kullanım:

  • RTC join için data.agora.appId, data.agora.channelName, data.agora.token, data.agora.uid.
  • RTM login için data.rtm.appId, data.rtm.userId, data.rtm.token.
  • RTM channel/message akışı için data.rtm.channelName.
  • Token süre kontrolü için data.rtm.expiresAt.

TypeScript Tipleri

type BaseResponse<T> = {
  isSuccess: boolean;
  statusCode: number;
  data: T;
  errors: string[];
  timestamp: string;
};

type AgoraRtcToken = {
  appId: string;
  channelName: string;
  token: string;
  uid: number;
  role: "host" | "guest" | "audience";
  expiresAt: string;
};

type AgoraRtmToken = {
  appId: string;
  channelName: string;
  userId: string;
  token: string;
  expiresAt: string;
};

type LiveStreamJoinResponse = BaseResponse<{
  liveStream: unknown;
  agora: AgoraRtcToken;
  rtm: AgoraRtmToken;
}>;

Mobil Kullanım Akışı

  1. Kullanıcı yayına girmeden önce rolüne göre join endpoint'ini çağır.
  2. Response'tan data.agora ile RTC oturumunu başlat.
  3. Response'tan data.rtm ile RTM client login işlemini yap.
  4. RTM login başarılıysa data.rtm.channelName kanalına katıl veya signalıng mesaj akışını başlat.
  5. Ekrandan çıkışta RTM channel leave ve RTM logout çağır.

Örnek:

const joinResponse = await api.joinLiveStream({ liveStreamId, role: "audience" });

const { agora, rtm } = joinResponse.data;

await rtcClient.join(agora.appId, agora.channelName, agora.token, agora.uid);

await rtmClient.login({
  uid: rtm.userId,
  token: rtm.token,
});

const rtmChannel = await rtmClient.createChannel(rtm.channelName);
await rtmChannel.join();

Web Kullanım Akışı

Web tarafında aynı response alanları kullanılmalıdır. Token localStorage gibi kalıcı alanlarda tutulmamalı, sayfa oturumu, React state veya stream orchestration service içinde saklanmalıdır.

Paket

Web client tarafında RTC için agora-rtc-sdk-ng, RTM için agora-rtm-sdk kullanılmalıdır.

npm install agora-rtm-sdk

RTM Service

RTM client sadece browser tarafında initialize edilmelidir. Next.js kullanılıyorsa service içinde dynamic import kullanmak SSR hatalarını engeller.

type AgoraRtmConfig = {
  appId: string;
  channelName: string;
  userId: string;
  token: string;
  expiresAt: string;
};

type AgoraRtmMessageHandler = (message: unknown, memberId: string) => void;

export class AgoraRtmService {
  private client: any | null = null;
  private channel: any | null = null;

  async login(config: AgoraRtmConfig, onMessage?: AgoraRtmMessageHandler) {
    if (typeof window === "undefined") return;

    if (new Date(config.expiresAt).getTime() <= Date.now()) {
      throw new Error("Agora RTM token expired");
    }

    await this.logout();

    const AgoraRTM = await import("agora-rtm-sdk");
    this.client = AgoraRTM.default.createInstance(config.appId);

    await this.client.login({
      uid: config.userId,
      token: config.token,
    });

    this.channel = this.client.createChannel(config.channelName);

    if (onMessage) {
      this.channel.on("ChannelMessage", onMessage);
    }

    await this.channel.join();
  }

  async sendChannelMessage(text: string) {
    if (!this.channel) return;
    await this.channel.sendMessage({ text });
  }

  async logout() {
    if (this.channel) {
      await this.channel.leave().catch(() => undefined);
      this.channel = null;
    }

    if (this.client) {
      await this.client.logout().catch(() => undefined);
      this.client = null;
    }
  }
}

export const agoraRtmService = new AgoraRtmService();

Join Response ile RTC + RTM Başlatma

const response = await fetch(`${API_BASE_URL}/api/v1/live-stream/join`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${accessToken}`,
  },
  body: JSON.stringify({ liveStreamId, role: "audience" }),
});

const payload: LiveStreamJoinResponse = await response.json();
const { agora, rtm } = payload.data;

await rtcClient.join(agora.appId, agora.channelName, agora.token, agora.uid);

await agoraRtmService.login(rtm, (message, memberId) => {
  console.log("RTM channel message", { message, memberId });
});

Creator ve guest için aynı service kullanılmalıdır. Tek fark endpoint seçimidir:

const creatorResponse = await api.post<LiveStreamJoinResponse>(
  "/api/v1/live-stream/join-as-creator",
  { liveStreamId },
);

const guestResponse = await api.post<LiveStreamJoinResponse>(
  "/api/v1/live-stream/join-as-guest",
  { liveStreamId },
);

React Hook Örneği

import { useCallback, useEffect, useRef } from "react";

export function useAgoraRtm() {
  const joinedRef = useRef(false);

  const joinRtm = useCallback(async (rtm: AgoraRtmConfig) => {
    await agoraRtmService.login(rtm, (message, memberId) => {
      console.log("RTM message received", { message, memberId });
    });

    joinedRef.current = true;
  }, []);

  const leaveRtm = useCallback(async () => {
    joinedRef.current = false;
    await agoraRtmService.logout();
  }, []);

  useEffect(() => {
    return () => {
      if (joinedRef.current) {
        void agoraRtmService.logout();
      }
    };
  }, []);

  return { joinRtm, leaveRtm };
}

Stream Lifecycle Entegrasyonu

Web uygulamasındaki stream lifecycle akışı şu sırayı takip etmelidir:

  1. join, join-as-creator veya join-as-guest endpoint'i çağrılır.
  2. data.agora ile RTC channel join yapılır.
  3. data.rtm ile RTM login ve channel join yapılır.
  4. Kullanıcı ekrandan çıkarken önce RTM channel leave/logout, sonra RTC leave/track cleanup çalışır.

Örnek lifecycle parçası:

const { agora, rtm, liveStream } = joinResponse.data;

await streamOrchestrator.initializeStream({
  streamId: liveStream.id,
  channelName: agora.channelName,
  token: agora.token,
  uid: agora.uid,
  appId: agora.appId,
  role: StreamRole.AUDIENCE,
  broadcasters: mapBroadcasters(agora.broadcasters, liveStream.creator),
  streamData: liveStream,
  userId: rtm.userId,
});

await agoraRtmService.login(rtm);

Cleanup:

await agoraRtmService.logout();
await streamOrchestrator.cleanupStream();

Token Süresi ve Hata Yönetimi

  • rtm.expiresAt geçmişse RTM login denemesi yapılmamalıdır.
  • RTM login token expired hatası alırsa kullanıcıya yeniden yayına giriş akışı başlatılmalıdır.
  • RTM token kısa ömürlüdür; uygulama kalıcı storage'a yazmamalıdır.
  • agora.uid ile rtm.userId aynı tip değildir: RTC için numeric uid, RTM için string userId kullanılmalıdır.
  • Backend response'unda rtm yoksa client bu sürümü eski backend kabul edip RTM signalıng'i devre dışı bırakmalı veya kullanıcıya tekrar deneme göstermelidir.

On this page