如何从 Python 中的 Youtube URL 流式传输音频(无需下载)?

Posted

技术标签:

【中文标题】如何从 Python 中的 Youtube URL 流式传输音频(无需下载)?【英文标题】:How to stream audio from a Youtube URL in Python (without download)? 【发布时间】:2018-08-27 11:56:31 【问题描述】:

我一直在尝试创建一种直接从 python 代码流式传输 youtube url(最好只有音频,尽管这并不重要)的方法。我尝试了很多东西,但似乎都没有真正奏效。到目前为止,我能够使用 youtube 数据 api 搜索视频或播放列表,抓取第一个视频或播放列表并将其传递给 pafy 以获得不同的流 url。有谁知道通过python播放youtube音频/视频而不先下载视频的方法?我认为可以使用 mplayer 或 vlc 等 cmd 行工具使用子进程弹出打开 cmd 行的 cmd 并传入 url,但我被卡住了。需要任何帮助。请!这是我的以下代码:

import argparse
import pafy
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

DEVELOPER_KEY = 'DEVELOPER KEY'
YOUTUBE_API_SERVICE_NAME = 'youtube'
YOUTUBE_API_VERSION = 'v3'

def pafy_video(video_id):
    url = 'https://www.youtube.com/watch?v=0'.format(video_id)
    vid = pafy.new(url)

def pafy_playlist(playlist_id)
    url = "https://www.youtube.com/playlist?list=0".format(playlist_id)
    playlist = pafy.get_playlist(url)


def youtube_search(options):
  youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)

  search_response = youtube.search().list(
    q='Hello world',
    part='id,snippet',
    maxResults=options.max_results
  ).execute()

  videos = []
  playlists = []
  channels = []
  for search_result in search_response.get('items', []):
    if search_result['id']['kind'] == 'youtube#video':
      videos.append('%s' % (search_result['id']['videoId']))
    elif search_result['id']['kind'] == 'youtube#channel':
      channels.append('%s' % (search_result['id']['channelId']))
    elif search_result['id']['kind'] == 'youtube#playlist':
      playlists.append('%s' % (search_result['id']['playlistId']))


  if videos:
    print('Videos:0'.format(videos))
    pafy_video(videos[0])
  elif playlists:
    print('Playlists:0'.format(playlists))
    pafy_video(playlists[0])

  #https://www.youtube.com/watch?v=rOU4YiuaxAM
  #url = 'https://www.youtube.com/watch?v=0'.format(videos[0])
  #print(url)

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--q', help='Search term', default='Google')
  parser.add_argument('--max-results', help='Max results', default=3)
  args = parser.parse_args()
  youtube_search(args)

Tldr;我想直接从 python 代码流式传输 youtube 视频(使用 url 或 id)而不先下载视频

谢谢!

【问题讨论】:

【参考方案1】:

pafy 根据其documentation 不直接列出正在播放的媒体(至少我没有找到)。

不过我们可以用它获取正确的url,然后用vlc等播放器直接播放,不用下载。

您可以下载vlc from here

首先我们使用pafyyoutube获得正确/最佳URL

import pafy
import vlc

url = "https://www.youtube.com/watch?v=bMt47wvK6u0"
video = pafy.new(url)
best = video.getbest()
playurl = best.url

在这里playurl 是播放的最佳网址。 然后我们用VLC来播放。

Instance = vlc.Instance()
player = Instance.media_player_new()
Media = Instance.media_new(playurl)
Media.get_mrl()
player.set_media(Media)
player.play()

这将打开一个没有控件(播放/暂停/停止等)的窗口。 您可以在 repr 窗口或 python 提示符下运行这些命令(取决于您如何使用它) 您将需要相应地使用 vlc 命令构建一个,例如

>>> player.pause() #-- to pause video
>>> player.play()  #-- resume paused video. On older versions, 
                   #     this function was called resume
>>> player.stop()  #-- to stop/end video

【讨论】:

嘿阿尼尔。谢谢!我一直在阅读有关 vlc 的信息。你知道它是否适用于windows吗?当我安装它并在我的 python 脚本中运行它时,我得到了一个 windows os 错误。 OSError: [WinError 126] 找不到指定的模块。如果不能在windows上播放,有没有vlc的替代品? 嘿尼克。我有窗口 7 并使用 vlc 有一段时间了。所以是的,它有效。正确安装它的问题。尝试使用pip install python-vlc 安装。 好的,谢谢阿尼尔!我为 Windows 下载了常规的 vlc,我已经运行了 pip install python-vlc 但仍然没有运气。我继续收到该错误。然后我尝试将 vlc.py 包含在我的目录中,但随后得到 vlc 没有对象“实例”的错误。您认为您可以向我指出有关安装 python vlc 的任何指南吗?很抱歉给您带来麻烦,但感谢您所做的一切! 根据这个线程 ***.com/questions/35487490/python-bindings-for-vlc ,看起来您可能正在尝试在 64 位 python 上安装 32 位 VLC。您可能正在使用 vlc.exe(Windows 上的 vlc 播放器应用程序)。您可能想要删除所有类型的 vlc(应用程序、python 包等)。然后重新开始。总是在 SO 上寻找以前的答案。在这里查看一个:superuser.com/questions/1281731/… 我发现了这个问题。如果你使用的是64位,那就安装vlc,然后在这里安装一个64位的vlc播放器:get.videolan.org/vlc/3.0.11/win64/vlc-3.0.11-win64.exe这样做,应该没有错误。【参考方案2】:

实现这一点的最佳方法是将mpv 与youtube-dl 一起使用(一种带有命令行控制台的轻量级媒体播放器,可让您通过复制和粘贴网址将任何类型的视频/音频编解码器流式传输到mpv 控制台(适用于 cmd 和终端)。用法:path\to\mpv https://your/video/audioURL.com/

首先导入这些模块 - 通过pip install bs4 requests安装

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)

这里的目标是使用此搜索查询来提取第一个视频结果的输出标题和链接。然后,我们可以使用urllib(例如"https://www.youtube.com/results?search_query=linkin+park+numb")使用标识符对youtube url "https://www.youtube.com/results?search_query="进行结束编码

formatUrl = urllib.request.urlopen("https://www.youtube.com/results?" + query_string)

这里re.findall(r"watch\?v=(\S11)"查看我们查询的所有视频结果的11个字符标识符

search_results = re.findall(r"watch\?v=(\S11)", formatUrl.read().decode())

解码内容后,我们可以通过连接主 youtube url 和 11 个字符标识符来提取完整​​的 url

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)
输出 ==> https://www.youtube.com/watch?v=kXYiU_JCYtU

为了进一步检查内容,我们可以使用beautifulsoup 来抓取视频的确切标题

inspect = BeautifulSoup(clip.content, "html.parser")
yt_title = inspect.find_all("meta", property="og:title")

for concatMusic1 in yt_title:
    pass

print(concatMusic1['content'])
输出 ==> Numb (Official Video) - Linkin Park

最后,要播放我们的音乐,我们将其输入到命令行

subprocess.Popen(
"start /b " + "path\\to\\mpv.exe" + clip2 + " --no-video --loop=inf --input-ipc-server=\\\\.\\pipe\\mpv-pipe > output.txt",
shell=True)

完整脚本

================================================ =====================

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=(\S11)", 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)

【讨论】:

以上是关于如何从 Python 中的 Youtube URL 流式传输音频(无需下载)?的主要内容,如果未能解决你的问题,请参考以下文章

使用url从python流传输youtube音频而无需下载python

如何使用 youtube-dl 从播放列表中的 Youtube 视频中提取上传日期、标题、URL 和持续时间?

我需要一些帮助来纠正我在 php 中的代码 - 如何从 YouTube URL 获取视频 ID [重复]

如何使用 Java 中的正则表达式从 YouTube URL 获取视频 ID

如何从 Youtube 向 discord bot python 发送视频

使用 Python 和 Regex 从 URL 获取 YouTube 视频 ID