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

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

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

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

並列処理

複数の計算が同時に実行される手法

YouTube

YouTubeとはユーザーがビデオをアップロード・共有・閲覧できるビデオ共有ウェブサイトです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

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

解決済

実行可能な処理が残っているのにも関わらず処理が終了する

saba0592
saba0592

総合スコア3

Discord

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

並列処理

複数の計算が同時に実行される手法

YouTube

YouTubeとはユーザーがビデオをアップロード・共有・閲覧できるビデオ共有ウェブサイトです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

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

1回答

0評価

0クリップ

421閲覧

投稿2021/12/22 16:14

編集2021/12/22 22:59

前提・実現したいこと

Musicクラスのplay()、もしくはloop()を実行した際にYTDLSource.from_url()以降を処理したい。

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

Musicクラスのplay()、もしくはloop()を実行するとYTDLSource.from_url()を実行する行で処理が終了し、次以降を処理してくれない。

該当のソースコード

Python

import asyncio import discord from discord.ext import commands import traceback import youtube_dl import os import urllib.request import re # Suppress noise about console usage from errors youtube_dl.utils.bug_reports_message = lambda: '' prefix = os.getenv('DISCORD_BOT_PREFIX', default='>') lang = os.getenv('DISCORD_BOT_LANG', default='ja') token = 'token' ytdl_format_options = { 'format': 'bestaudio/best', 'outtmpl': '%(extractor)s-%(id)s-%(title)s.mp3', 'restrictfilenames': True, 'noplaylist': True, 'nocheckcertificate': True, 'ignoreerrors': False, 'logtostderr': False, 'quiet': True, 'no_warnings': True, 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192', }], 'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes: True } ffmpeg_options = { 'options': '-vn' } ytdl = youtube_dl.YoutubeDL(ytdl_format_options) class YTDLSource(discord.PCMVolumeTransformer): def __init__(self, source, *, data, volume=0.2): 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): loop = loop or asyncio.get_event_loop() data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=False)) if 'entries' in data: # take first item from a playlist data = data['entries'][0] filename = data['url'] ytdl.prepare_filename(data) return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data) class AudioQueue(asyncio.Queue): def __init__(self): super().__init__(100) def __getitem__(self, idx): return self._queue[idx] def to_list(self): return list(self._queue) def remove(self, idx): del self._queue[idx] def reset(self): self._queue.clear() class AudioStatus: def __init__(self, ctx: commands.Context, vc: discord.VoiceClient): self.vc: discord.VoiceClient = vc self.ctx: commands.Context = ctx self.queue = AudioQueue() self.playing = asyncio.Event() self.loopMode = False asyncio.create_task(self.playing_task()) async def add_audio(self, title, path): await self.queue.put([title, path]) def get_list(self): return self.queue.to_list() def remove(self, idx): self.queue.remove(idx) def reset(self): self.queue.reset() async def playing_task(self): while True: self.playing.clear() if self.loopMode: title, player = self.queue[0] else: title, player = await self.queue.get() self.vc.play(player, after=self.play_next) if not self.loopMode: await self.ctx.send(f'{title}を再生します。') await self.playing.wait() def play_next(self, err=None): self.playing.set() async def leave(self): self.queue.reset() if self.vc: await self.vc.disconnect() self.vc = None @property def is_playing(self): return self.vc.is_playing() def resume(self): self.vc.stop() def pause(self): self.vc.stop() def stop(self): self.vc.stop() class Music(commands.Cog): def __init__(self, bot): self.bot = bot self.audio_statuses = "" # command to connect to voice channel @commands.command(aliases=["s"]) async def start(self, ctx): """Joins a voice channel""" if ctx.author.voice is None: await ctx.send('先にボイスチャンネルに接続してください…。') else: if ctx.guild.voice_client: if ctx.author.voice.channel == ctx.guild.voice_client.channel: await ctx.send('既に接続済みです…。') else: await ctx.voice_client.disconnect() await asyncio.sleep(0.5) vc = await ctx.author.voice.channel.connect() self.audio_statuses = AudioStatus(ctx, vc) await ctx.send('ボイスチャンネルを変更しました。') else: vc = await ctx.author.voice.channel.connect() self.audio_statuses = AudioStatus(ctx, vc) await ctx.send('ボイスチャンネルに接続しました。') # command to play sound from a youtube URL or add to queue @commands.command(aliases=["pl"]) async def play(self, ctx, *, entry): """Play music""" status = self.audio_statuses status.loopMode = False queue = status.get_list player = await Music.get_player(ctx, entry) if len(queue) != 0: await ctx.send(f'`{player.title}`を追加しました。') await status.add_audio(player.title, player) # command to loop play sound from a youtube URL @commands.command(aliases=["l"]) async def loop(self, ctx, *, entry): """Loop play music""" status = self.audio_statuses status.loopMode = True player = await Music.get_player(ctx, entry) await status.reset() await ctx.send(f'`{player.title}`を追加しました。') await status.add_audio(player.title, player) @classmethod async def get_player(self, ctx, entry): if entry.startswith('http') is True: url = entry else: search_keyword = entry.replace(" ", "+") regex = r'[^\x00-\x7F]' matchedList = re.findall(regex, search_keyword) for m in matchedList: search_keyword = search_keyword.replace(m, urllib.parse.quote_plus(m, encoding="utf-8")) html = urllib.request.urlopen("https://www.youtube.com/results?search_query=" + search_keyword) video_ids = re.findall(r"watch?v=(\S{11})", html.read().decode()) url = "https://www.youtube.com/watch?v=" + video_ids[0] async with ctx.typing(): return await YTDLSource.from_url(url, loop=self.bot.loop) bot = commands.Bot(command_prefix=prefix, description='Relatively simple music bot example') @bot.event async def on_ready(): print('Logged in as {0} ({0.id})'.format(bot.user)) print('------') await bot.change_presence(activity=discord.Game(name=f'{prefix}hでコマンド一覧', type=1)) @bot.event async def on_command_error(ctx, error): if isinstance(error, commands.errors.CommandNotFound): await ctx.send('存在しないコマンドです…。') elif isinstance(error, commands.errors.MissingRequiredArgument): await ctx.send('引数が足りません…。') elif isinstance(error, commands.CommandError): pass else: orig_error = getattr(error, 'original', error) error_msg = ''.join(traceback.TracebackException.from_exception(orig_error).format()) await ctx.send("不明なエラーが発生…。") await bot.get_channel(チャンネルID).send(error_msg) print(error_msg) bot.add_cog(Music(bot)) bot.run(token)

試したこと

①get_player()を削除して該当処理をplay()の中で処理してみた。→YTDLSource.from_url()の行までは進んだが、そこで処理が終了。
②get_player()の次の行にprint()を記述→実行されたがprint()以降は実行されず。
③デバッグしてみた。→YTDLSource.from_url()の行までは進んだが、そこでステップインを行うと処理が終了。
④YTDLSource.from_url()をコメントアウトし、別の戻り値を設定。→同じ箇所で処理が終了する。
⑤YTDLSource.from_url()だけをplay()の中で実行→③と同じ
⑥スタックトレースを確認→出力なし

補足情報(FW/ツールのバージョンなど)

Python 3.9.5
youtube-dl 2021/12/17
ffmpeg 4.4

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Discord

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

並列処理

複数の計算が同時に実行される手法

YouTube

YouTubeとはユーザーがビデオをアップロード・共有・閲覧できるビデオ共有ウェブサイトです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

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