Skip to content

Instantly share code, notes, and snippets.

@cosven
Created February 6, 2020 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cosven/8f7053930c20162f8f6e50150e0c2c3d to your computer and use it in GitHub Desktop.
Save cosven/8f7053930c20162f8f6e50150e0c2c3d to your computer and use it in GitHub Desktop.
FeelUOwn YouTube provider
import os
import time
import json
import subprocess
from fuocore.provider import AbstractProvider
from fuocore.models import SongModel
no_proxy_list = [
'.126.net',
'.qq.com',
'.bilibili.com',
'.acgvideo.com',
'.xiami.com',
'.163.com',
'.xiami.net',
]
os.environ['http_proxy'] = 'http://127.0.0.1:1087'
os.environ['no_proxy'] = ','.join(no_proxy_list)
APP = app # noqa
IDENTIFIER = 'youtube'
NAME = 'YouTube'
class Provider(AbstractProvider):
@property
def identifier(self):
return IDENTIFIER
@property
def name(self):
return NAME
provider = Provider()
APP.library.register(provider)
class YoutubeModel(SongModel):
source = IDENTIFIER
class Meta:
provider = provider
allow_get = False
@property
def url(self):
if hasattr(self, '_url') and self._expire_at < time.time():
return self._url
vurl = "https://youtube.com/v/" + self.identifier
p = subprocess.run(['youtube-dl', '-g', vurl],
capture_output=True)
if p.returncode == 0:
video = audio = ''
for line in p.stdout.decode().splitlines():
if 'mime=video' in line:
video = line
if 'mime=audio' in line:
audio = line
if audio:
self.url = audio
return audio
return ''
@url.setter
def url(self, url):
self._url = url
# from old experience, will be expired after 5 hour
self._expire_at = time.time() + 3600 * 5
@property
def duration_ms(self):
"""hack: there is a bug in SongModel.duration_ms implementation"""
return '00:00'
def _generate_models(url):
p = subprocess.run(['youtube-dl', '-j', '--flat-playlist', url],
capture_output=True)
models = []
if p.returncode == 0:
stdout = p.stdout
for line in stdout.decode().splitlines():
meta = json.loads(line)
if '_type' in meta:
if meta['_type'] != 'url':
continue
identifier = meta['url']
title = meta['title']
else:
# TODO: we can extract complete song info here
identifier = meta['id']
title = meta['title']
model = YoutubeModel(identifier=identifier,
title=title,)
models.append(model)
return models
def _play_models(models):
for model in models:
print('add-to-playlist: {}'.format(model))
APP.playlist.add(model)
APP.player.play_song(models[0])
def play_youtube(url):
models = _generate_models(url)
if models:
print('found {} song'.format(len(models)))
_play_models(models)
else:
print('no available song found')
# play_youtube('https://music.youtube.com/playlist?list=OLAK5uy_luGzxd76PlO-rZN-Nh_MRoD81ukS_D7os')
@cosven
Copy link
Author

cosven commented Feb 6, 2020

用法

  1. 安装最新版 youtube-dl
  2. 下载上述脚本
  3. 修改第 20 行,将 proxy 地址改成一个自己的(否则可能有未知问题)
  4. 执行 fuo exec < youtube_provider.py

播放周杰伦的叶惠美专辑,执行

fuo exec "play_youtube('https://music.youtube.com/playlist?list=OLAK5uy_luGzxd76PlO-rZN-Nh_MRoD81ukS_D7os')"

播放 no matter what

fuo exec "play_youtube('https://www.youtube.com/watch?v=7eul_Vt6SZY')"

最佳实践

~/.fuorc 中进行配置,代码如下(请自己修改目录)

import os
when('app.initialized',
     lambda *args: source(os.path.expanduser('~/coding/rcfiles/youtube_provider.py')))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment