読み上げてくれればチャット欄見なくていいよねってことで、Youtube APIからライブ配信のコメントをポーリングしつつ、取得したコメントを読み上げさせようとTryしました。
主に処理部分についての話をします
要素
Youtube API(Data API, Live Streaming API)
今回使用するAPIは以下です。いずれもAPIキーで認証します
Videos:https://developers.google.com/youtube/v3/docs/videos/list?hl=ja
動画IDを引数にデータを取得し、チャットIDを取得します
// VideoResponseは省略
export interface IVideoApi{
list(videoId:string) :Promise<VideoResponse>
}
export class VideoApi implements IVideoApi{
private readonly key:string
constructor(key:string){
this.key = key
}
list(videoId:string): Promise<VideoResponse> {
const config: AxiosRequestConfig = {
params:{
part: "liveStreamingDetails",
id: videoId,
key:this.key
}
}
return axios.get("https://www.googleapis.com/youtube/v3/videos", config).then(r => r.data)
}
}
LiveChatMessages:https://developers.google.com/youtube/v3/live/docs/liveChatMessages/list
チャットIDを引数にコメントを取得します。レスポンスのpageTokenを引数に使用することでコメントをつづきから取得できるので、apiのパラメータは初回/それ以降の2種類にしました。
// LiveChatMessagesResponseは省略
export class LiveChatMessagesApi implements ILiveChatMessagesApi{
private readonly key:string = ""
constructor(key:string){
this.key = key
}
async startList(liveChatId: string, maxResults: number, nextPageToken: string | null): Promise<LiveChatMessagesResponse> {
let config: AxiosRequestConfig
if (nextPageToken === null) {
config = {
params:{
liveChatId,
part: "id,snippet,authorDetails",
maxResults,
key:this.key
}
}
} else {
config = {
params:{
liveChatId,
part: "id,snippet,authorDetails",
maxResults,
key:this.key,
pageToken:nextPageToken
}
}
}
const response = await axios.get("https://www.googleapis.com/youtube/v3/liveChat/messages", config)
return response.data
}
}
SpeechSynthesis
文字列を読み上げさせる
export interface ISpeaker{
speak(txt:string):void
}
export class Speaker implements ISpeaker{
// 設計の都合上クラスにしているが、この関数だけで良い
speak(txt: string): void {
const synthes = new SpeechSynthesisUtterance(txt)
synthes.lang = "ja-JP"
speechSynthesis.speak(synthes)
}
}
処理のイメージ
- 角丸長方形はオブジェクト、長方形は処理
- 実線は処理の流れ、点線はオブジェクトへの参照
- APIからコメント取得するのと読み上げは非同期ループ
というイメージです
読み上げたものの履歴
をUIに表示させればWebアプリとしてはある程度の形になります。(ユーザー名、コメント内容は黄色で伏せてます)