ytdl-core を使用して YouTube の音源を配信するサンプル
Discord.js とは別に音源取得用に ytdl-core 、再生用に @discordjs/voice
2024/5/20追記: 現在のバージョンでは@discordjs/opus等のopusにエンコードするためのライブラリは不要です
#TODO @discordjs/opusが不要になったのはいつか調べるtig.icon @discordjs/voiceはGUILD_VOICE_STATES intentを必要とする
!yt YouTube の動画URLに反応してボイスチャンネルで再生するコード
code:js
const ytdl = require('ytdl-core');
const { entersState, AudioPlayerStatus, createAudioPlayer, createAudioResource, joinVoiceChannel, StreamType } = require('@discordjs/voice');
client.on('messageCreate', async message => {
// メッセージが "!yt" からはじまっていてサーバー内だったら実行する
if (!message.content.startsWith('!yt') || !message.guild) {
return;
}
// メッセージから動画URLだけを取り出す
const url = message.content.split(' ')1; if (!ytdl.validateURL(url)) return message.reply(${url}は処理できません。);
// コマンドを実行したメンバーがいるボイスチャンネルを取得
const channel = message.member.voice.channel;
// コマンドを実行したメンバーがボイスチャンネルに入ってなければ処理を止める
if (!channel) return message.reply('先にボイスチャンネルに参加してください!');
// チャンネルに参加
const connection = joinVoiceChannel({
adapterCreator: channel.guild.voiceAdapterCreator,
channelId: channel.id,
guildId: channel.guild.id,
selfDeaf: true,
selfMute: false,
});
const player = createAudioPlayer();
connection.subscribe(player);
// 動画の音源を取得
const stream = ytdl(ytdl.getURLVideoID(url), {
filter: format => format.audioCodec === 'opus' && format.container === 'webm', //webm opus
quality: 'highest',
});
const resource = createAudioResource(stream, {
inputType: StreamType.WebmOpus
});
// 再生
player.play(resource);
await entersState(player,AudioPlayerStatus.Playing, 10 * 1000);
await entersState(player,AudioPlayerStatus.Idle, 24 * 60 * 60 * 1000);
// 再生が終了したら抜ける
connection.destroy();
});
Discord.js とは別に音源取得用に ytdl-core 、再生用に @discordjs/opus と ffmpeg-static が必要
$ npm install ytdl-core @discordjs/opus ffmpeg-static
このコードは v12 で動くように書かれているので、そのままでは v11 では動かない message.member.voice.channel → message.member.voiceChannel
connection.play → connection.playStream
dispatcher.once('finish', ...)→dispatcher.on('end', ...)
!yt YouTube の動画URLに反応してボイスチャンネルで再生するコード
code:js
const ytdl = require('ytdl-core')
client.on('message', async message => {
// メッセージが "!yt" からはじまっていてサーバー内だったら実行する
if (message.content.startsWith('!yt') && message.guild) {
// メッセージから動画URLだけを取り出す
const url = message.content.split(' ')1 // まず動画が見つからなければ処理を止める
if (!ytdl.validateURL(url)) return message.reply('動画が存在しません!')
// コマンドを実行したメンバーがいるボイスチャンネルを取得
const channel = message.member.voice.channel
// コマンドを実行したメンバーがボイスチャンネルに入ってなければ処理を止める
if (!channel) return message.reply('先にボイスチャンネルに参加してください!')
// チャンネルに参加
const connection = await channel.join()
// 動画の音源を取得
const stream = ytdl(ytdl.getURLVideoID(url), { filter: 'audioonly' })
// 再生
const dispatcher = connection.play(stream)
// 再生が終了したら抜ける
dispatcher.once('finish', () => {
channel.leave()
})
}
})
トラブルシューティング
v13のほうはffmpegに依存しないように書いたつもりなのだけど…tig.icon
なので、よければこれが起きたら動画URLなどを教えていただけると嬉しいです。