티스토리 뷰

*이 글은 python 버전 3.6, discord.py 버전 0.16.12 기준으로 작성된 글입니다.*


디스코드 봇으로 유튜브 재생하기


디스코드 봇에는 다양한 기능이 존재합니다. 

이번 시간에는 디스코드 봇의 기능 중 하나인 유튜브 재생 기능을 사용해 보도록 하겠습니다.

먼저 이 기능을 사용하기 전에는 설치해야 하는 프로그램들이 있습니다.


다운로드

cmd - pip install youtube_dl

FFmpeg 설치


사용하는 라이브러리

discord

asyncio

youtube_dl

re

재생기능


제가 사용하고 있는 유튜브 재생 코드입니다.

위 사진을 클릭하면 소스코드가 있는 깃허브로 연결됩니다.

이렇게만 봐서는 알아보기가 힘들어서 부분을 나눠서 살펴보도록 하겠습니다.

if message.content.startswith("!음악"): #음성채널에 봇을 추가 및 음악 재생
	msg = message.content.split(" ")
	try:
		url = msg[1]
		url1 = re.match('(https?://)?(www\.)?((youtube\.(com))/watch\?v=([-\w]+)|youtu\.be/([-\w]+))', url) #정규 표현식을 사용해 url 검사
		if url1 == None:
			await client.send_message(message.channel, embed=discord.Embed(title=":no_entry_sign: url을 제대로 입력해주세요.",colour = 0x2EFEF7))
			return
	except IndexError:
		await client.send_message(message.channel, embed=discord.Embed(title=":no_entry_sign: url을 입력해주세요.",colour = 0x2EFEF7))
		return

메시지가 !음악으로 시작할 때 URL을 입력받고 저장하는 코드입니다.

split 함수를 사용해 문자열을 나누고 URL에 해당하는 부분을 정규 표현식을 사용해 유튜브 링크인지 검색합니다.

그 다음 URL이 유튜브 링크가 아니거나 URL 입력이 없을 때 오류 문구를 출력합니다.

channel = message.author.voice.voice_channel 
server = message.server
voice_client = client.voice_client_in(server)

1번째 줄은 메시지를 보낸 사람이 접속해있는 음성채널을 받아오는 코드입니다.

2~3번째 줄은 조건문을 사용하기 위해 봇이 음성채널에 있으면 그 음성채널도 받아옵니다.

if client.is_voice_connected(server) and not playerlist[server.id].is_playing(): #봇이 음성채널에 접속해있으나 음악을 재생하지 않을 때
	await voice_client.disconnect()

봇이 음성채널에 있는데 음악을 재생하지 않을 때 다시 재생하기 위해 봇이 음성채널에서 나가는 코드입니다.

elif client.is_voice_connected(server) and playerlist[server.id].is_playing(): #봇이 음성채널에 접속해있고 음악을 재생할 때
	player = await voice_client.create_ytdl_player(url,after=lambda:queue(server.id),before_options="-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5")
	if server.id in que: #큐에 값이 들어있을 때
		que[server.id].append(player)
	else: #큐에 값이 없을 때
		que[server.id] = [player]
	await client.send_message(message.channel, embed=discord.Embed(title=":white_check_mark: 추가 완료!",colour = 0x2EFEF7))
	playlist.append(player.title) #재생목록에 제목 추가
	return

봇이 음성채널에 접속해있고 음악을 재생하고 있을 때 실행되는 코드입니다.

입력받은 URL을 youtube_dl로 다운로드 받고 큐에 데이터들을 저장합니다.

def queue(id): #음악 재생용 큐
	if que[id] != []:
		player = que[id].pop(0)
		playerlist[id] = player
		del playlist[0]
		player.start()

만들어 둔 큐입니다. 노래제목과 다운로드 받은 데이터들을 저장하는 용도입니다.

try:
	voice_client = await client.join_voice_channel(channel)
except discord.errors.InvalidArgument: #유저가 음성채널에 접속해있지 않을 때
	await client.send_message(message.channel, embed=discord.Embed(title=":no_entry_sign: 음성채널에 접속하고 사용해주세요.",colour = 0x2EFEF7))
	return

저장된 음성채널로 봇이 들어오는 코드입니다. 저장된 음성채널이 없을 경우 오류를 출력합니다.

try:
	player = await voice_client.create_ytdl_player(url,after=lambda:queue(server.id),before_options="-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5")
	playerlist[server.id] = player
	playlist.append(player.title)
except youtube_dl.utils.DownloadError: #유저가 제대로 된 유튜브 경로를 입력하지 않았을 때
	await client.send_message(message.channel, embed=discord.Embed(title=":no_entry_sign: 존재하지 않는 경로입니다.",colour = 0x2EFEF7))
	await voice_client.disconnect()
	return
player.start()

입력받은 url을 이용해 영상을 재생하는 코드입니다.

큐에 youtube_dl로 다운로드 받은 데이터와 동영상의 제목을 저장하고 노래를 재생합니다.

만약 URL이 정상적인 영상의 경로가 아닐 때 오류 메시지를 출력합니다.

종료, 스킵기능

if message.content == "!종료": #음성채널에서 봇을 나가게 하기
	server = message.server
	voice_client = client.voice_client_in(server)

	if voice_client == None: #봇이 음성채널에 접속해있지 않았을 때
		await client.send_message(message.channel, embed=discord.Embed(title=":no_entry_sign: 봇이 음성채널에 없어요.",colour = 0x2EFEF7))
		return
		
	await client.send_message(message.channel, embed=discord.Embed(title=":mute: 채널에서 나갑니다.",colour = 0x2EFEF7)) #봇이 음성채널에 접속해있을 때
	await voice_client.disconnect()

재생기능을 만들었으면 이제 종료기능도 만들어보겠습니다.

봇이 위치한 음성채널을 받아와 그 음성채널에서 나가게 하는 코드입니다. 

봇이 음성채널에 접속해있지 않으면 오류 메시지를 출력합니다.

if message.content == "!스킵":
	id = message.server.id
	if not playerlist[id].is_playing(): #재생 중인 음악이 없을 때
		await client.send_message(message.channel, embed=discord.Embed(title=":no_entry_sign: 스킵할 음악이 없어요.",colour = 0x2EFEF7))
		return
	await client.send_message(message.channel, embed=discord.Embed(title=":mute: 스킵했어요.",colour = 0x2EFEF7))
	playerlist[id].stop()

종료기능은 단순히 봇이 음성채널에서 나가는 기능입니다. 그렇기에 노래를 1개씩 건너뛰고 싶을 때는 사용할 수 없습니다.

그럴 때를 대비해 스킵기능도 만들겠습니다. 종료기능처럼 코드는 매우 간단합니다.

메시지가 작성된 서버의 ID를 받아 큐에 저장된 ID와 비교하고 음악이 재생 중일 때 그 음악을 종료합니다.

재생목록기능

if message.content == "!목록":

	if playlist == []:
		await client.send_message(message.channel, embed=discord.Embed(title=":no_entry_sign: 재생목록이 없습니다.",colour = 0x2EFEF7))
		return

	playstr = "```css\n[재생목록]\n\n"
	for i in range(0, len(playlist)):
		playstr += str(i+1)+" : "+playlist[i]+"\n"
	await client.send_message(message.channel, playstr+"```")

재생 중인 노래의 제목과 대기 중인 노래의 목록을 확인하고 싶어 재생목록기능도 추가했습니다.

재생목록이 비어있지 않을 경우 재생목록을 출력합니다.

댓글
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Total
Today
Yesterday