質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

4457閲覧

DiscordのBOTを通話に参加させてyoutubeから音楽を再生させるには!?!?

Winter_1214

総合スコア11

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/06/24 15:57

前提・実現したいこと

!joinでvcに参加させて、!disconnectでvcから切断させて、!play_○○で音楽を再生させたいです。
どうしてもわからなかったので、質問させていただきました。わかる人がいらっしゃいましたら、
お答えしていただけると幸いです。どうぞよろしくお願い致します。

発生している問題・エラーメッセージ

AttributeError: 'Member' object has no attribute 'voice_channel'

該当のソースコード

python

1import asyncio 2import discord 3import youtube_dl 4from discord.ext import commands 5 6 7#client = discord.Client() 8client = commands.Bot(command_prefix = '!') 9 10player = {} 11 12@client.command(pass_context=True) 13async def join(ctx): 14 channel = ctx.message.author.voice_channel 15 await client.join_voice_channel(channel) 16 17@client.command(pass_context=True) 18async def disconnect(ctx): 19 server = ctx.message.server 20 voice_client = client.voice_client_in(server) 21 await voice_client.disconnect() 22 23@client.command(pass_context=True) 24async def play(ctx, url): 25 server = ctx.message.server 26 voice_client = client.voice_client_in(server) 27 player = await voice_client.create_ytdl_player(url) 28 players[server.id] = player 29 player.start() 30 31client.run(自分のtoken)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

まずエラーは'Memberの中にvoice_channelという属性はありませんよとゆうものなんです。
おそらくどこかのサイトを参考にしながらコードを書かれているとは思いますが、
古いdiscord.py(以下d.pyと略す)ではMember.voice_channelがありましたが、
現在のd.pyではMember.voice.channelに変わっています。
またほかにも
ctx.message.server→ctx.message.guild
await client.join_voice_channel(channel)→channel.connect()
などいろいろ仕様変更がありこのままではエラーまみれ全く動かない状態です。
なので古いd.pyを入れなおすか新しいd.pyの仕様に合わせて書き直すかですね。

新しいd.pyの仕様でyoutube-dl関連の日本語記事が簡単に検索した限りではないため、参考になりそうなソースのリンクだけ載せます。
github Rapptz/RoboDanny/discord.py/examples/basic_voice.py

自分はBot commands frameworkの書き方に詳しくないので解説はできませんが、
このサンプルコードで動かすことはできました。

追記(1)
自分がBot commands frameworkを使えないので
全部on_messageで処理します
あとこのサンプルソースほぼ内容は上記リンクと一緒で
上記リンクの機能縮小版になります(_p 曲名orURL:joinして再生開始/_dis:ボイスdisconnect)

python

1import asyncio 2 3import discord 4import youtube_dl 5 6from discord.ext import commands 7#この辺は何やってるかわからないけどそのまま引用 8# Suppress noise about console usage from errors 9youtube_dl.utils.bug_reports_message = lambda: '' 10 11 12ytdl_format_options = { 13 'format': 'bestaudio/best', 14 'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s', 15 'restrictfilenames': True, 16 'noplaylist': True, 17 'nocheckcertificate': True, 18 'ignoreerrors': False, 19 'logtostderr': False, 20 'quiet': True, 21 'no_warnings': True, 22 'default_search': 'auto', 23 # bind to ipv4 since ipv6 addresses cause issues sometimes 24 'source_address': '0.0.0.0' 25} 26 27ffmpeg_options = { 28 'options': '-vn' 29} 30 31ytdl = youtube_dl.YoutubeDL(ytdl_format_options) 32 33 34class YTDLSource(discord.PCMVolumeTransformer): 35 def __init__(self, source, *, data, volume=0.5): 36 super().__init__(source, volume) 37 38 self.data = data 39 40 self.title = data.get('title') 41 self.url = data.get('url') 42 43 @classmethod 44 async def from_url(cls, url, *, loop=None, stream=False): 45 loop = loop or asyncio.get_event_loop() 46 data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream)) 47 48 if 'entries' in data: 49 # take first item from a playlist 50 data = data['entries'][0] 51 52 filename = data['url'] if stream else ytdl.prepare_filename(data) 53 return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data) 54 55 56bot = commands.Bot(command_prefix=commands.when_mentioned_or("_"), 57 description='Relatively simple music bot example') 58 59 60@bot.event 61async def on_ready(): 62 print('Logged in as {0} ({0.id})'.format(bot.user)) 63 print('------') 64#この辺は何やってるかわからないけどそのまま引用ここまで 65 66@bot.event 67async def on_message(message): 68 69 if message.content.startswith("_p "): 70 await message.author.voice.channel.connect()#vc接続 71 message.content=message.content.replace("_p ","") 72 async with message.channel.typing(): 73 player = await YTDLSource.from_url(message.content, loop=asyncio.get_event_loop())#多分再生用の素材を作ってるとこ 74 message.author.guild.voice_client.play(player, after=lambda e: print( 75 'Player error: %s' % e) if e else None)#再生してるとこ 76 await message.channel.send('Now playing: {}'.format(player.title)) #再生中のタイトルをsend 77 78 if message.content.startswith("_dis"): 79 await message.author.guild.voice_client.disconnect() #VC切断 80 81 82bot.run("TOKEN")

投稿2020/06/25 00:25

編集2020/06/25 09:58
sanaN

総合スコア38

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Winter_1214

2020/06/25 08:17

!joinと!disconnectは出来ました!!ありがとうございます。 !playのほうは下の参考リンクを見ましたが、出来ませんでした。 もしよろしかったら、そのサンプルコードもいただいてもよろしいですか??
sanaN

2020/06/25 10:01

一応追記しました。 ただほぼリンクソースそのままですし、自分がyoutube-dlの詳細がわからないので解説はできないです
Winter_1214

2020/06/25 10:06

追記ありがとうございます。 わかりました。追記のやつを試してみますね。
Winter_1214

2020/06/25 14:33

何度もすみません。 曲を連投したい場合はどうしたらよろしいでしょうか??
Winter_1214

2020/06/25 15:08

わかりました。試してみます。 あと、下のやつcommandでできますかね? 追記で使えないっていってるのに、すみません。 ```pyhon @client.command(pass_context=True) async def join(ctx): channel = ctx.message.author.voice.channel await channel.connect() async with ctx.typing(): player = await YTDLSource.from_url(url, loop=self.client.loop, stream=True) ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None)#再生してるとこ await ctx.send('Now playing: {}'.format(player.title)) ```
Winter_1214

2020/06/26 09:19

見ながらすると、コマンドフレームワークでできました!! 本当に助かりました。でも、連投の仕方がやっぱりよくわかりません....
退会済みユーザー

退会済みユーザー

2021/05/25 12:28

import asyncio import discord import youtube_dl # Suppress noise about console usage from errors youtube_dl.utils.bug_reports_message = lambda: '' ytdl_format_options = { 'format': 'bestaudio/best', 'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s', 'restrictfilenames': True, 'noplaylist': True, 'nocheckcertificate': True, 'ignoreerrors': False, 'logtostderr': False, 'quiet': True, 'no_warnings': True, 'default_search': 'auto', 'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes } ffmpeg_options = { 'options': '-vn' } ytdl = youtube_dl.YoutubeDL(ytdl_format_options) class YTDLSource(discord.PCMVolumeTransformer): def __init__(self, source, *, data, volume=0.5): super().__init__(source, volume) self.data = data self.title = data.get('title') self.url = data.get('url') @classmethod async def from_url(cls, url, *, loop=None, stream=False): loop = loop or asyncio.get_event_loop() data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream)) if 'entries' in data: # take first item from a playlist data = data['entries'][0] filename = data['url'] if stream else ytdl.prepare_filename(data) return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data) client = discord.Client() @client.event async def on_message(message: discord.Message): # メッセージの送信者がbotだった場合は無視する if message.author.bot: return if message.content == "!join": if message.author.voice is None: await message.channel.send("あなたはボイスチャンネルに接続していません。") return # ボイスチャンネルに接続する await message.author.voice.channel.connect() await message.channel.send("接続しました。") elif message.content == "!leave": if message.guild.voice_client is None: await message.channel.send("接続していません。") return # 切断する await message.guild.voice_client.disconnect() await message.channel.send("切断しました。") elif message.content.startswith("!play "): if message.guild.voice_client is None: await message.channel.send("接続していません。") return # 再生中の場合は再生しない if message.guild.voice_client.is_playing(): await message.channel.send("再生中です。") return url = message.content[6:] # youtubeから音楽をダウンロードする player = await YTDLSource.from_url(url, loop=client.loop) # 再生する await message.guild.voice_client.play(player) await message.channel.send('{} を再生します。'.format(player.title)) elif message.content == "!stop": if message.guild.voice_client is None: await message.channel.send("接続していません。") return # 再生中ではない場合は実行しない if not message.guild.voice_client.is_playing(): await message.channel.send("再生していません。") return message.guild.voice_client.stop() await message.channel.send("ストップしました。")
退会済みユーザー

退会済みユーザー

2021/05/25 12:28

こんな感じのどうですか?なんか間違ってる気がしますけど
guest

0

有難うございます!
参考になりましたでしょうか?

投稿2021/05/27 10:11

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

import asyncio

import discord
import youtube_dl

Suppress noise about console usage from errors

youtube_dl.utils.bug_reports_message = lambda: ''

ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes
}

ffmpeg_options = {
'options': '-vn'
}

ytdl = youtube_dl.YoutubeDL(ytdl_format_options)

class YTDLSource(discord.PCMVolumeTransformer):
def init(self, source, *, data, volume=0.5):
super().init(source, volume)

self.data = data

self.title = data.get('title')
self.url = data.get('url')

@classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))

if 'entries' in data:

take first item from a playlist

data = data['entries'][0]

filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)

client = discord.Client()

@client.event
async def on_message(message: discord.Message):

メッセージの送信者がbotだった場合は無視する

if message.author.bot:
return

if message.content == "!join":
if message.author.voice is None:
await message.channel.send("あなたはボイスチャンネルに接続していません。")
return

ボイスチャンネルに接続する

await message.author.voice.channel.connect()
await message.channel.send("接続しました。")

elif message.content == "!leave":
if message.guild.voice_client is None:
await message.channel.send("接続していません。")
return

切断する

await message.guild.voice_client.disconnect()

await message.channel.send("切断しました。")
elif message.content.startswith("!play "):
if message.guild.voice_client is None:
await message.channel.send("接続していません。")
return

再生中の場合は再生しない

if message.guild.voice_client.is_playing():
await message.channel.send("再生中です。")
return

url = message.content[6:]

youtubeから音楽をダウンロードする

player = await YTDLSource.from_url(url, loop=client.loop)

再生する

await message.guild.voice_client.play(player)

await message.channel.send('{} を再生します。'.format(player.title))

elif message.content == "!stop":
if message.guild.voice_client is None:
await message.channel.send("接続していません。")
return

再生中ではない場合は実行しない

if not message.guild.voice_client.is_playing():
await message.channel.send("再生していません。")
return

message.guild.voice_client.stop()

await message.channel.send("ストップしました。")
どうですか?難しいですが...どっか間違ってるかも

投稿2021/05/26 11:56

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問