728x90
반응형

⚠ 야매로 만든 것이니 따라하지 않는 것을 추천합니다

lektion-von-erfolglosigkeit.tistory.com/96 <-새로운 방법

이제 봇이 음성채널에 입장하거나 퇴장할 수 있으니 본격적으로 음악을 재생시켜보자

 

FFmpeg

www.ffmpeg.org/

 

FFmpeg

Converting video and audio has never been so easy. $ ffmpeg -i input.mp4 output.avi     News October 5th, 2019, Bright Lights FFmpeg has added a realtime bright flash removal filter to libavfilter. Note that this filter is not FDA approved, nor are we me

www.ffmpeg.org

FFmpeg은 디지털 음성 스트림과 영상 스트림에 대해서 다양한 종류의 형태로 기록하고 변환하는 컴퓨터 프로그램이다 (Wikipedia)

 

간단히 말해서 그냥 파일 인코더 겸 플레이어다

mp4 파일을 mp3로 바꾼다거나...

 

들어가자마자 있는 Download 버튼을 누르고 Window builds from gyan.dev를 클릭

 

아래로 스크롤하여 release를 찾고 full-shared 버전을 받아주자 쥰내 오래걸렸다. youtube_dl 먼저 설치하고 다시 오자

다운로드가 끝났다면 압축해제한 뒤 환경변수를 등록해야 한다

 

제어판 - 시스템 - 고급 시스템 설정 - 고급 - 환경 변수 - path - 새로 만들기 - 설치한 경로\bin로 등록

여기저기 찾기도 귀찮으니 그냥 디스코드 봇 파일이 있는 곳에 압축해제 했다. 이러면 사실 환경변수 등록 안해도...

 

마지막으로 cmd나 powershell 등에서 아래 명령어를 입력해 잘 설치되었는지 확인한다.

ffmpeg -version

만약 안된다면 껐다 키자

 

youtube_dl

youtube-dl 은 YouTube 및 1000 개가 넘는 다른 비디오 호스팅 웹 사이트의 비디오 및 오디오 콘텐츠를위한 오픈 소스다운로드 관리자 입니다 (Wikipedia)

dl을 보고 감이 왔다면 대단하다. download의 약자다.

이름에서 알수 있듯이 유튜브 영상을 다운로드해주는 라이브러리다.

 

python3 -m pip install -U youtube_dl
더보기

저번과 마찬가지로 혹시나 wsl같이 리눅스를 사용하고 있다면 "youtube-dl"로 수정하여 사용한다.

 

코드 추가

역시나 메인 파일과 코드를 분리했다. 또한 run.py를 main.py로 이름을 바꿨다.

#ydl.py
import youtube_dl #youtube_dl

def ydl(url):
	ydl_opts = { #다운로드 옵션
    	'format': 'bestaudio/best',
        'postprocessors': [{
        	'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
            }],
        'outtmpl': 'song.mp3', #파일 이름
		}
	with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    	ydl.download([url]) #다운로드

ydl_opts는 다운로드 옵션을 설정하는 것으로 노래만 재생하기 때문에 mp3파일로 받아준다.

outtmpl는 파일 이름을 설정하는데 일단은 하기 쉽도록 song.mp3로 설정했다.

나중에 제목 그대로 받아서 재생목록을 만들 예정

 

#main.py 추가
...
from ydl import * #ydl.py import

...

@bot.command()
async def play(ctx, url):
	ydl(url) #음원 다운로드
    
    channel = ctx.message.voice.channel
    voice = await channel.connect() #음성채널 접속
    voice.play(discord.FFmpegPCMAudio(executable = './ffmpeg/bin/ffmpeg.exe', source='./song.mp3')) #다운받은 음원 재생
    
    while voice.is_playing(): #노래 재생동안 딜레이
    	sleep(.1)
    
    await voice.disconnect() #재생이 끝나면 나가기

수많은 시행착오를 겪으며 만들다 보니 저번에 만들었던 join명령어와 leave 명령어가 쓸모 없어졌다.

어차피 노래재생할 때 아니면 봇이 음성채널에 들어올 일도 없으니 기존에 있던 join과 leave는 삭제했다.

 

voice.play(discord.FFmpegPCMAudio(executable = './ffmpeg/bin/ffmpeg.exe', source='./song.mp3'))

이부분을 보면 executable(실행)과 source(파일)을 지정했는데 ./는 현재 위치를 뜻한다.

현재 디텍토리는 왼쪽 사진과 같이 되어 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

좀 아쉬운게 mp3파일이 실행파일(main.py)와 같은 폴더에 저장되는 건데 이건 좀 더 찾아봐야 할 것 같다.

어쨋든 실행하면 이제 봇이 노래를 틀어줄 것이다.

 

노래를 다운로드 후 인코딩하고 틀어야 해서 시간이 조금 걸리지만 성공

 

다른 곡 재생

그런데 다른 url을 넣어도 처음에 입력한 url의 노래만 재생된다.

이름을 죄다 song.mp3로 설정해놔서 생기는 문제인데 일단은 해결해보자

song.mp3 파일이 이미 존재한다.

간단하게 다운로드 하기전에 song.mp3파일이 있다면 삭제하면 될 것 같다.

import youtube_dl
import os #os모듈

file = './song.mp3' #파일 경로 설정

def ydl(url):
	if os.path.isfile(file): #song.mp3파일이 존재하면
    	os.remove(file) #파일 삭제
    
    ydl_opts = {
    	'format': 'bestaudio/best',
        'postprocessors': [{
        	'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
            }],
        'outtmpl': 'song.mp3',
		}
	with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    	ydl.download([url])

이제 다른 노래를 재생할 수 있다.

 

노래가 재생중일때 다른 곡 play 명령을 내리면 아무 일도 일어나지 않고 이미 파일이 존재해서 스킵했다는 말만 나온다.

 

노래 일시정지, 다시재생, 멈춤

이제 일시정지, 재생, 멈춤(스킵)을 만들어 보자

#main.py 추가
...

#일시정지
@bot.command()
async def pause(ctx):
	voice = discord.utils.get(bot.voice_clients, guild = ctx.guild) #봇의 음성 관련 정보
    if voice.is_playing(): #노래가 재생중이면
    	voice.pause() #일시정지
    else:
    	await ctx.send("재생중인 곡 없음") #오류(?)

#다시 재생        
@bot.command()
async def resume(ctx):
	voice = discord.utils.get(bot.voice_clients, guild = ctx.guild) #봇의 음성 관련 정보
    if voice.is_paused(): #일시정지 상태이면
    	voice.resume()
    else:
    	await ctx.send("일시정지 아님") #오류(?)
        
#정지
@bot.command()
async def stop(ctx):
	await bot.voice_clients[0].disconnect() #음성채널 나가기
    
...

discord.py는 봇의 음성에 대해서 일시정지와 다시재생을 제공하고 있다.

그리고 stop 명령어는 그냥 봇을 음성채널에서 퇴장시켰더니 문제 없이 잘 되었다...

 

다음에는 뭘 만들까 다음에는 유저 데이터를 작성해서 나 혼자 게임을 해볼예정이다