라이브 스트리밍 (AWS-IVS) 개발기 - 4

박상하·2025년 5월 8일

1년차

목록 보기
15/26

Player 기본 구현

이번 역시 공식 홈페이지를 기준으로 설명해보자

<script src="https://player.live-video.net/1.39.0/amazon-ivs-player.min.js"></script>

먼저 Player sdk는 npm을 통해 설치하지 않고 script 태그를 head에 넣어주었다.
가져온 sdk를 통해 player를 생성하고 시작할 수 있다.

   const ivs = (window as any).IVSPlayer;
            if (!ivs?.isPlayerSupported) return;

            player = ivs.create();
            player.attachHTMLVideoElement(videoRef.current!);
            player.load(
                `재생URL`,
            );
            player.play();

그런데 만약 해당 스트리밍이 비공개 즉, 재생 권한 부여에
비디오 재생에 대한 토큰 권한 부여 요구 사항 활성화가 설정되어있다면
재생 URL 뒤에 발급받은 토큰 정보를 보내주어야한다.

자세한건 이곳에

이렇게 하면 player는 시작이된다.

또한 player는 timed metadata를 수신할 수 있다.

방법은 eventListener이다.

 player.addEventListener((window as any).IVSPlayer.PlayerEventType.TEXT_METADATA_CUE, e => {
                let getMetaData = e.text;
                getMetaData = JSON.parse(getMetaData);

                if (getMetaData.value?.eject) {
                    switch (getMetaData.type) {
                        case 'notice':
                            console.log(metaData);
                            setMetaData(current => current.filter(item => item.type !== 'notice'));
                            break;
                        case 'product':
                            setMetaData(current =>
                                current.filter(item => item.value.title !== getMetaData.value.title),
                            );
                            break;
                        case 'coupon':
                            setMetaData(current =>
                                current.filter(item => item.value.title !== getMetaData.value.title),
                            );
                            break;
                        case 'vote':
                            setMetaData(current =>
                                current.filter(item => item.value.title !== getMetaData.value.title),
                            );
                            break;
                    }
                } else {
                    setMetaData(current => [...current, getMetaData]);
                }
            });

필자는 이렇게 설정했다.

만약 eject와 관련된 메타데이터의 경우엔 type에 대한 value로 분기를 처리하도록했다.
그 외의 eject가 아닌 경우는 배열로 계속 metadata를 주입하여 overlay product에 적용하였다.

 {metaData.map(meta => (
                <PlayerOverlay type={meta.type} value={meta.value} />
            ))}

또한 신경 쓴 부분은 방송 상태(시청자 수, 방송 컨디션, 네트워크 지연 등)를 체크하는 부분이다.
이 부분은 트러블 슈팅 과정으로 따로 게시글로 작성하겠다.

Chat 기본 구현

$ npm install --save amazon-ivs-chat-messaging

을 통해 SDK를 설치한다.

그리고 Chat room을 만든다. 이는 aws 콘솔에서 먼저 만들어야한다.

여기서 room에 대한 설정을 거쳐 생성 한 후

const room = new ChatRoom({
  regionOrUrl: 'ap-northeast-2',
  tokenProvider: tokenProvider,
});

room을 생성한다.

tokenProvider를 매개변수로 넣어주어야하는데 tokenProvider는 ChatToken을 만들어주는 Provider이다.

type ChatToken = {
  token: string;
  sessionExpirationTime?: Date;
  tokenExpirationTime?: Date;
}


function tokenProvider(): Promise<ChatToken> {

  return {
    token: "<token>",
    sessionExpirationTime: new Date("<date-time>"),
    tokenExpirationTime: new Date("<date-time>")
  }
}

api를 호출해서 token, sessionExpirationTime, tokenExpirationTime을 받아 프로바이더에 return 한다.

필자는 백엔드 개발자분께서 token 로직을 다 짜주셔서 해당 API만 호출하면 됐다..ㅎㅎ
(client에서도 token 생성은 가능하지만 aws 계정이나 민감정보가 들어가기 때문에 안전을 위해!)

    const [tokenInfo, setTokenInfo] = React.useState<ReceivedIvsToken | null>(null);

    React.useEffect(() => {
        const initIvsToken = async () => {
            const response = await getIvsToken();
            setTokenInfo(response.data);
        };
        initIvsToken();
    }, []);

이렇게 tokenInfo를 받아와 props로 전달하는 방식으로 구현했다.
사실 props로 전달하지 않아도 chat 컴포넌트 내부에서 호출해도 되지만
우리 서비스는 chat과 Player Token이 하나의 API에서 오기 때문에 부모 컴포넌트에서 호출 후
props로 전달하도록 로직을 구성했다.

Receive Events

그럼 이제 Chat에서 받는 Event는 어떻게 인터렉션할 수 있을까?

Event는
1. 채팅연결
2. 채팅연결중
3. 채팅강퇴
4. 메세지 받음
5. 이벤트 리시브
6. 메세지 삭제

등이 있다. 필자가 헷갈렸던 부분은 메세지 받음이다.

aws ivs chat은 내가 보낸 메세지도 결국 메시지 받음 이벤트로 처리가 되기 때문에
클라이언트에서 chat에 대한 내용을 따로 관리할 필요가 없다.
(이것 때문에 채팅 한 번 치면 두 번 노출됨..)
결국 aws ivs chat도 내부적으로 websocket으로 작동하기때문이다.

     const room = new ChatRoom({
            regionOrUrl: 'ap-northeast-2',
            tokenProvider: () => tokenProvider(tokenInfo),
        });
        roomRef.current = room;

        const unsubscribeOnConnecting = room.addListener('connecting', () => console.log('연결중'));
        const unsubscribeOnConnected = room.addListener('connect', () => console.log('연결됨'));
        const unsubscribeOnDisconnected = room.addListener('disconnect', () => {});
        const unsubscribeOnMessageReceived = room.addListener('message', );
        const unsubscribeOnEventReceived = room.addListener('event', event => {
        });
        const unsubscribeOnMessageDelete = room.addListener('messageDelete', () => {});
        const unsubscribeOnUserDisconnect = room.addListener('userDisconnect', () => {});

        room.connect();

마무리

이렇게 Broadcast, Chat, Player의 간단한 세팅이 끝났다.

이제 트러블 슈팅, 대시보드, 채팅 강퇴 후 방송 차단 등 좀 더 심화적인 작업 내용을 포스팅할 계획이다!

많관부 🍀

0개의 댓글