How to stream audio from a Youtube URL in Python (without download)?
pafy
according to its documentation do not list playing media directly (at least I didn't find any).
However we can use it to get correct url, and then use player such as vlc
to play directly without downloading.
You can download vlc from here
First we get correct / best URL from youtube
using pafy
import pafy
import vlc
url = "https://www.youtube.com/watch?v=bMt47wvK6u0"
video = pafy.new(url)
best = video.getbest()
playurl = best.url
Over here playurl
is best URL to play.
Then we use VLC to play it.
Instance = vlc.Instance()
player = Instance.media_player_new()
Media = Instance.media_new(playurl)
Media.get_mrl()
player.set_media(Media)
player.play()
This will open a window with no controls (play/pause/stop etc).
You can run these command on the repr
window or at python prompt (depending upon how you are using it)
You will need to build one accordingly using vlc commands such as
>>> player.pause() #-- to pause video
>>> player.play() #-- resume paused video. On older versions,
# this function was called resume
>>> player.stop() #-- to stop/end video
The best way to accomplish this is to use mpv with youtube-dl (a light weight media player that comes with a command line console which allows you to stream any type of video/audio codecs via copy and pasting url to mpv console (works for cmd and terminal). Usage: path\to\mpv https://your/video/audioURL.com/
First import these modules - install via pip install bs4 requests
import re, requests, subprocess, urllib.parse, urllib.request
from bs4 import BeautifulSoup
Then create a variable to store music title of your choice
music_name = "Linkin Park Numb"
query_string = urllib.parse.urlencode({"search_query": music_name})
The goal here to use this search query to extract the output title and link of the first video result. We can then endcode the youtube url "https://www.youtube.com/results?search_query="
with the identifier using urllib
(eg., "https://www.youtube.com/results?search_query=linkin+park+numb"
)
formatUrl = urllib.request.urlopen("https://www.youtube.com/results?" + query_string)
This right here re.findall(r"watch\?v=(\S{11})"
views the 11 character identifier of all the video results from our query
search_results = re.findall(r"watch\?v=(\S{11})", formatUrl.read().decode())
After decoding the content, we can extract the full url by concatenating the main youtube url with the 11 character identifier
clip = requests.get("https://www.youtube.com/watch?v=" + "{}".format(search_results[0]))
clip2 = "https://www.youtube.com/watch?v=" + "{}".format(search_results[0])
print(clip2)
- Output ==>
https://www.youtube.com/watch?v=kXYiU_JCYtU
To further inspect the content, we can use beautifulsoup to scrape the extact title of the video
inspect = BeautifulSoup(clip.content, "html.parser")
yt_title = inspect.find_all("meta", property="og:title")
for concatMusic1 in yt_title:
pass
print(concatMusic1['content'])
- Output ==>
Numb (Official Video) - Linkin Park
Finally, to play our music we input this to the command line
subprocess.Popen(
"start /b " + "path\\to\\mpv.exe" + clip2 + " --no-video --loop=inf --input-ipc-server=\\\\.\\pipe\\mpv-pipe > output.txt",
shell=True)
Full script
===================================================================
import re, requests, subprocess, urllib.parse, urllib.request
from bs4 import BeautifulSoup
music_name = "Linkin Park Numb"
query_string = urllib.parse.urlencode({"search_query": music_name})
formatUrl = urllib.request.urlopen("https://www.youtube.com/results?" + query_string)
search_results = re.findall(r"watch\?v=(\S{11})", formatUrl.read().decode())
clip = requests.get("https://www.youtube.com/watch?v=" + "{}".format(search_results[0]))
clip2 = "https://www.youtube.com/watch?v=" + "{}".format(search_results[0])
inspect = BeautifulSoup(clip.content, "html.parser")
yt_title = inspect.find_all("meta", property="og:title")
for concatMusic1 in yt_title:
pass
print(concatMusic1['content'])
subprocess.Popen(
"start /b " + "path\\to\\mpv.exe " + clip2 + " --no-video --loop=inf --input-ipc-server=\\\\.\\pipe\\mpv-pipe > output.txt",
shell=True)
# Alternatively, you can do this for simplicity sake:
# subprocess.Popen("start /b " + "path\\to\\mpv.exe " + clip2 + "--no-video", shell=True)