Next.js와 100ms로 제작된 Video Chat App
개시하다
안녕하세요.황금주 잘 보냈어?
비정기적으로 이전 회사 동기들과 온라인 점심을 먹었는데 줌과 메트가 무료 계좌라면 3인 이상이면 시간 제한이 있잖아요.나는 이 제한을 좋아하지 않아서 영상 채팅 소프트웨어를 만드는 이야기를 썼다.
(회사에서 쉬는 시간에 점심을 먹기 때문에 한 시간은 문제없다.)
100ms
이번에 사용100ms한 거 아세요?
며칠 전에 읽었다이 블로그.써보려고
100ms는 개발자가 웹, 안드로이드, iOS 애플리케이션에 동영상 음성 회의를 추가하는 클라우드 플랫폼이라고 한다.
100ms is a cloud platform that allows developers to add video and audio conferencing to Web, Android and iOS applications.
첫 페이지에는'몇 시간이면 라이브 앱을 만들 수 있다'고 적혀 있지만 하루 정도 화상채팅 앱을 완성했기 때문에 틀림없다.
빨리 100ms로 영상통화 앱을 실현하세요!
사전 준비
우선 100ms로 계정을 만들어야 합니다.이 페이지부터 등록하십시오.
자유계획은 매달 10000분을 사용할 수 있기 때문에 이번 목적은 충분하다.
등록 후 "Createa newapp"페이지로 이동합니다. 다음 질문에 답하십시오.
시험을 준비하다
사실 이렇게 하면 영상통화를 할 수 있다.위 화면의 "Join as statge"를 클릭하여 앞 페이지로 이동, 룸에 들어가면 화상 채팅이 시작됩니다!
화면 구축, 맞춤형 제작 등 필요 없는 사람은 이걸로 하면 될 것 같아요.
GOAL
지금부터 실시되는 코드의 완성 형식은여기.이기 때문에 문장을 읽는 것이 번거로운 분들은 직접 코드를 참조하세요.
실현하고자 하는 기능은 다음과 같다.
· 참가·탈퇴 영상채팅
• 마이크 켜기/끄기
• 카메라 켜기/끄기
• 화면 공유 켜기/끄기
· 스피커·마이크·카메라의 설비 변경
전제 조건
Next.js 사용* React
Install
우선 환경을 조정해야 한다.
npx create-next-app --ts demo_100ms
cd demo_100ms
npm i @100mslive/react-sdk react@17 react-dom@17
라이브러리 초기화
먼저 100ms를 사용할 수 있도록 제작된 React 애플리케이션에서 초기화합니다.
HMSRoomProvider
import과 랩만 있으면 됩니다.// src/pages/_app.tsx
import '../styles/globals.css';
import type { AppProps } from 'next/app';
import { HMSRoomProvider } from '@100mslive/react-sdk';
function MyApp({ Component, pageProps }: AppProps) {
return (
{/* HMSRoomProviderでラップする */}
<HMSRoomProvider>
<Component {...pageProps} />
</HMSRoomProvider>
);
}
export default MyApp;
콘셉트
구체적인 실시에 들어가기 전에 필요한 키워드를 소개한다.
Room 참가
hmsActions
의join
방법을 사용하여 Room에 참가합니다.이 방법을 사용하려면
userName
와 authToken
가 필요하다.userName
는 참가자가 임의로 결정하는 문자열이다.authToken
계기판에서 복사해 왔어요.authToken 복제
※ 롤이 할 수 없는 일을 제한하기 때문에 필요에 따라 다른 롤톡을 복제하세요.이번에는 모든 참가자가 같은 기능을 사용할 수 있도록 한 라운드를 치르기로 했다.
이루어지다
// src/components/JoinForm/index.tsx
import { ChangeEvent, FormEvent, useState, VFC } from 'react';
import { useHMSActions } from '@100mslive/react-sdk';
export const JoinForm: VFC = () => {
const hmsActions = useHMSActions();
const [userName, setUserName] = useState('');
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setUserName(e.target.value);
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
// joinメソッドにuserNameと先ほどコピーしたauthTokenを渡す
hmsActions.join({
userName,
// tokenはenvファイルから呼び出してます
authToken: process.env.NEXT_PUBLIC_STAGE_TOKEN || "",
});
};
return (
<form onSubmit={handleSubmit}>
<h2>Join Room</h2>
<div>
<label htmlFor="user_name">User Name:</label>
<input
type="text"
id="user_name"
name="name"
required
value={userName}
onChange={handleChange}
/>
</div>
<button type="submit">Join</button>
</form>
);
};
Room 종료
룸에 참가할 수 있어서 탈퇴할 수 있어요.
사용
hmsActions
의leave
방법을 종료합니다.페이지를 떠나는 시간에 탈퇴
onunload
할 수 있도록 불이 났습니다.// src/components/Home/index.tsx
import { useHMSActions } from '@100mslive/react-sdk';
import { useEffect, VFC } from 'react';
export const Home: VFC = () => {
const hmsActions = useHMSActions();
useEffect(() => {
window.onunload = () => {
hmsActions.leave();
};
}, [hmsActions]);
return <div>Home</div>;
};
참여자 비디오 표시
이어서 참가자들의 동영상이 표시됩니다.
참가자의 정보는
useHMSStore
에 대한 매개 변수 전달selectPeers
을 통해 수조로 얻을 수 있다.각 사람의 영상은
useVideo
의 매개 변수에 videoTrack
에 건네주고 반환된 ref
를 video
라벨에 연결한 후에 나타난다.// src/components/VideoChat/index.tsx
import { selectPeers, useHMSStore } from '@100mslive/react-sdk';
import type { VFC } from 'react';
import { Peer } from './Peer';
export const VideoChat: VFC = () => {
const peers = useHMSStore(selectPeers);
return (
<div>
{peers.map((peer) => (
<Peer key={peer.id} peer={peer} />
))}
</div>
);
};
// src/components/VideoChat/Peer/index.tsx
import { HMSPeer, useVideo } from '@100mslive/react-sdk';
import type { VFC } from 'react';
type Props = {
peer: HMSPeer;
};
export const Peer: VFC<Props> = ({ peer }) => {
const { videoRef } = useVideo({
trackId: peer.videoTrack,
});
return (
<div>
<video
ref={videoRef}
autoPlay
muted
playsInline
// 映像が反転するのでcssで対処
style={{ transform: 'scaleX(-1)' }}
/>
<span>
{/* ユーザ名はnameプロパティを参照することで取得可能 */}
{peer.name} {peer.isLocal && '(You)'}
</span>
</div>
);
};
상태에 따라 어셈블리 분할
최소한의 설치가 완료되었기 때문에 제작된 구성 요소를 첫 페이지에 연결합니다.
useHMSStore
를 selectIsConnectedToRoom
에 건네주면 isConnected
를 받을 수 있으며, 이를 토대로 룸에 가입 여부를 판단하고 구성 요소를 분리한다.import { useHMSStore, selectIsConnectedToRoom, useHMSActions } from '@100mslive/react-sdk';
import { useEffect, VFC } from 'react';
import { VideoChat } from '../VideoChat';
import { JoinForm } from '../JoinForm';
export const Home: VFC = () => {
const hmsActions = useHMSActions();
const isConnected = useHMSStore(selectIsConnectedToRoom);
useEffect(() => {
window.onunload = () => {
// Roomに参加している時、という条件分岐追加
if (isConnected) {
hmsActions.leave();
}
};
}, [hmsActions, isConnected]);
// Roomに参加していればVideoChat、そうでなければJoinFormを表示する
return <>{isConnected ? <VideoChat /> : <JoinForm />}</>;
};
완성되면 룸에 한번 참가해 보세요!JoinForm으로 사용자 이름을 입력해서 참가하고 싶으면 카메라의 이미지가 표시됩니다.
(첫 번째 브라우저에서는 마이크와 카메라에 접근할 수 있는 대화상자가 나타날 수 있습니다. 허락해 주십시오.)
컨트롤러 추가
이제 추가 기능을 구현합니다.
마이크 켜기/끄기
마이크의 켜기/끄기 사용
useAVToggle
의 반환값toggleAudio
방법은 현재 상태isLocalAudioEnabled
에서 확인할 수 있습니다.// src/components/VideoChat/Controller/AudioController/index.tsx
import { useAVToggle } from '@100mslive/react-sdk';
import type { VFC } from 'react';
export const AudioController: VFC = () => {
const { isLocalAudioEnabled, toggleAudio } = useAVToggle();
return (
// 省略
);
};
카메라 켜기/끄기
useAVToggle
반환치toggleVideo
의 방법을 사용하여 현재 상태isLocalVideoEnabled
를 확인할 수 있습니다.// src/components/VideoChat/Controller/index.tsx
import { useAVToggle } from '@100mslive/react-sdk';
import type { VFC } from 'react';
export const VideoController: VFC = () => {
const { isLocalVideoEnabled, toggleVideo } = useAVToggle();
return (
// 省略
);
};
화면 공유 켜기/끄기
화면 공유도 간단하게 실현할 수 있다.단지
hmsActions
의setScreenShareEnabled
방법에 표지를 제출할 뿐이다.현재 상태는 useHMSStore
를 selectIsLocalScreenShared
에 맡기면 된다.// src/components/VideoChat/Controller/ScreenShareController/index.tsx
import { selectIsLocalScreenShared, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
import type { VFC } from 'react';
import { Switch } from '@headlessui/react';
export const ScreenShareController: VFC = () => {
const hmsActions = useHMSActions();
// 自分が画面共有しているかどうか
const amIScreenSharing = useHMSStore(selectIsLocalScreenShared);
const handleToggleShareScreen = async () => {
try {
// 現在の状態を反転したものを引数に渡してtoggleする
await hmsActions.setScreenShareEnabled(!amIScreenSharing);
} catch (error) {
console.error({ error });
}
};
return (
// 省略
);
};
화면 공유 내용은 비디오 태그에 연결하여 표시할 수 있습니다.이를 위해서는 화면 공유 내용의 트랙이 필요하다.selectScreenShareByperID를 사용하면 id를 키로 화면이 공유하는 정보를 얻고useHMSStore에 전달할 수 있습니다.
이번 실장에서는 화면을 공유했다면 카메라 영상이 아닌 화면 공유를 한곳으로 옮겼다.
// src/components/VideoChat/Peer/index.tsx
import { HMSPeer, selectScreenShareByPeerID, useHMSStore, useVideo } from '@100mslive/react-sdk';
import type { VFC } from 'react';
type Props = {
peer: HMSPeer;
};
export const Peer: VFC<Props> = ({ peer }) => {
const screenshareVideoTrack = useHMSStore(selectScreenShareByPeerID(peer.id));
const { videoRef } = useVideo({
// 画面供されたらそのidを渡して、されてなければ今まで通りvideoTrackを渡す
trackId: screenshareVideoTrack?.id ?? peer.videoTrack,
});
return (
// 省略
);
};
스피커 마이크 카메라 장치 변경
사용 가능한 장치 가져오기
사용 가능한 장치는
useHMSStore
에 전달selectDevices
을 통해 얻을 수 있다.반환값은
DeviceMap
의 유형으로 각 키를 배열할 수 있습니다.const devices = useHMSStore(selectDevices);
interface DeviceMap {
audioInput: MediaDeviceInfo[];
audioOutput: MediaDeviceInfo[];
videoInput: MediaDeviceInfo[];
}
현재 사용 중인 장치 가져오기
현재 사용 중인 장치는
useHMSStore
에 전달selectLocalMediaSettings
을 통해 얻을 수 있다.반환값은
HMSMediaSettings
의 형식으로 키마다 id를 얻을 수 있습니다.const selectedDevices = useHMSStore(selectLocalMediaSettings);
interface HMSMediaSettings {
audioInputDeviceId: string;
videoInputDeviceId: string;
audioOutputDeviceId?: string;
}
장치 변경
디바이스를 변경하려면 deviceId 를
hmsActions
에 전달하는 방법입니다.스피커의 변경
setAudioOutputDevice
, 마이크의 변경setAudioSettings
, 카메라의 변경 사용setVideoSettings
방법.매개 변수의 교부 방법이 다르다는 것을 주의하세요.const hmsActions = useHMSActions();
// スピーカーの変更
const handleChangeAudioOutput = (deviceId: string) => {
// 引数は文字列で渡す
hmsActions.setAudioOutputDevice(deviceId);
};
// マイクの変更
const handleChangeAudioInput = async (deviceId: string) => {
// 引数はオブジェクトで渡す
await hmsActions.setAudioSettings({ deviceId });
};
// カメラの変更
const handleChangeVideo = async (deviceId: string) => {
// 引数はオブジェクトで渡す
await hmsActions.setVideoSettings({ deviceId });
};
종료 버튼
페이지를 다시 불러와서 종료할 수 있기 때문에 종료 단추를 만들 수도 있습니다.
이것은 방금 소개한
hmsActions
방법leave
을 온클릭 처리 프로그램에 맡긴 것일 뿐이다.// src/components/VideoChat/Controller/LeaveButton/index.tsx
import { useHMSActions } from '@100mslive/react-sdk';
import type { VFC } from 'react';
export const LeaveButton: VFC = () => {
const hmsActions = useHMSActions();
const handleClick = () => {
hmsActions.leave();
};
return (
<button type="button" onClick={handleClick}>
Leave
</button>
);
};
비디오 채팅 화면에 컨트롤러 연결
마지막으로 제작된 컨트롤러를 하나의 구성 요소로 합쳐 영상 채팅 화면에 연결하면 된다.
// src/components/VideoChat/Controller/VideoController/index.tsx
import { selectPeers, useHMSStore } from '@100mslive/react-sdk';
import type { VFC } from 'react';
import { Controller } from './Controller';
import { Peer } from './Peer';
export const VideoChat: VFC = () => {
const peers = useHMSStore(selectPeers);
return (
<div>
<div>
{peers.map((peer) => (
<Peer key={peer.id} peer={peer} />
))}
</div>
{/* ページ下部に表示 */}
<Controller />
</div>
);
};
끝맺다
어때?
나는 이렇게 간단하게 동영상 채팅 소프트웨어를 만들 수 있을 줄 몰랐기 때문에 몇 시간 안에 만들 수 있을 것이라고 생각한다.
WebRTC를 업무적으로 처리하니까 배운다는 의미도 있지만 그 일대가 다 잘해서 아무것도 못 배울 것 같아서...
그것은 물론이고, 나는 동기로부터 FB로부터 편안한 온라인 점심 환경을 조정하고 싶다.
참고 자료
Reference
이 문제에 관하여(Next.js와 100ms로 제작된 Video Chat App), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/hakushun/articles/42ef2bc9e2d169텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)