最近打算把you-get放到kodi里面当一个视频插件,结果发现踩了好多坑。本来以为有现成函数可以直接调用,去搜了搜没找到,看了知乎这个https://www.zhihu.com/question/54939203问题,我表示服气的,高票教育一个小白去看文档。。。(然而根本没有开发文档可以看(小程序可以理解),文档里全是命令行用法,写程序根本没法用。费这时间要么你就直接告诉人家正确用法要么你就别回答,害得我找了那么久,不如直接说让我去直接看代码好了)底下还贴出几个代码,用os和sys.argv的,跟需求差得有点远,于是自己看代码。
上面纯属吐嘈。
目前kodi
的版本为18,master
分支仅支持python2,需要自行编译feature_python3
分支。
将you-get封装成为kodi模块,或者可以直接安装我封装好的:)
https://github.com/feilongfl/script.module.you_get
安装后即可。
这里有一个坑,直接封装会出现这个错误
ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <class 'AttributeError'>
Error Contents: 'xbmcout' object has no attribute 'buffer'
Traceback (most recent call last):
File "/home/feilong/.kodi/addons/plugin.youget/main.py", line 12, in <module>
from resources.lib import plugin
File "/home/feilong/.kodi/addons/plugin.youget/resources/lib/plugin.py", line 9, in <module>
from you_get import common as youget
File "/home/feilong/.kodi/addons/script.module.you_get/lib/you_get/common.py", line 22, in <module>
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')
AttributeError: 'xbmcout' object has no attribute 'buffer'
因为在kodi中使用xbmcout
没有buffer这个元素,实际用不到,注释掉就可以了
if sys.stdout.isatty():
default_encoding = sys.stdout.encoding.lower()
else:
default_encoding = locale.getpreferredencoding().lower()
这里也是同理,保留最后一行。
在kodi插件中添加
<import addon="script.module.you_get" version="0.4.1193"/>
准备工作结束,于是终于到了调用you-get的时候。
总之先上代码吧,懒得看后面的可以直接抄走:)不过这部分代码仅仅是测试使用,所以只能播放一个视频,没有其他功能,只是展示下调用方法。
# -*- coding: utf-8 -*-
import routing
import logging
import xbmcaddon
import sys
from you_get import common as youget
from xbmcgui import ListItem
from xbmcplugin import addDirectoryItem, endOfDirectory
import xbmc
ADDON = xbmcaddon.Addon()
plugin = routing.Plugin()
@plugin.route('/')
def index():
addDirectoryItem(plugin.handle, plugin.url_for(
show_category, "one"), ListItem("Category One"), False)
addDirectoryItem(plugin.handle, plugin.url_for(
show_category, "two"), ListItem("Category Two"), True)
endOfDirectory(plugin.handle)
@plugin.route('/category/<category_id>')
def show_category(category_id):
runCmd([1,2])
addDirectoryItem(
plugin.handle, "", ListItem("Hello category %s!" % category_id))
endOfDirectory(plugin.handle)
def download_urls(
urls, title, ext, total_size, output_dir='.', refer=None, merge=True,
faker=False, headers={}, **kwargs
):
assert urls
print(urls)
playUrl(urls[0])
return
def playUrl(video_url):
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
playlist.clear()
li = ListItem(path=video_url)
li.setInfo( type="video", infoLabels={ "Path" : video_url } )
playlist.add(url=video_url, listitem=li)
xbmc.Player().play(playlist)
def test_main(**kwargs):
youget.script_main(youget.any_download, youget.any_download_playlist, **kwargs)
def runCmd(command):
extra = {}
URLs = ['https://www.youtube.com/watch?v=AnwQAWmGgek']
youget.set_socks_proxy("feilong-server.lan:10080")
youget.download_urls = download_urls
youget.download_main(
youget.any_download, youget.any_download_playlist,
URLs, False,
output_dir='/tmp/', merge=True,
info_only=False, json_output=False,
**extra
)
def run():
plugin.run()
emmm,上面就是插件部分代码了。
主要调用部分是runCmd,因为最开始看了知乎的sys.argv,后来发现输出都在stdout里面,不想重定向于是看代码。
导入youget这个没什么好说的,看这名字,看看知乎,看看这体积,看看main函数就决定是common了:)
from you_get import common as youget
如果是在桌面环境下播放视频,确实是可以通过类似下面这种用法来运行。
sys.argv=['you-get', 'https://www.youtube.com/watch?v=AnwQAWmGgek']
youget.main()
但是在kodi中,需要拦截视频url并将其传递给kodi,由kodi解码播放。然而我看了看,貌似最后都在调用download_urls这个函数来下载视频,于是重载这个函数
def download_urls(
urls, title, ext, total_size, output_dir='.', refer=None, merge=True,
faker=False, headers={}, **kwargs
):
assert urls
print(urls)
playUrl(urls[0])
return
youget.download_urls = download_urls
然后调用这个
youget.download_main(
youget.any_download, youget.any_download_playlist,
# URLs, args.playlist,
URLs, False,
# output_dir=args.output_dir, merge=not args.no_merge,
output_dir='/tmp/', merge=True,
info_only=False, json_output=False,
# password=args.password,
**extra
)
就可以播放了
顺便之前没有传递http的header,所以一些视频不能播放
def download_urls(
urls, title, ext, total_size, output_dir='.', refer=None, merge=True,
faker=False, headers={}, **kwargs
):
assert urls
print(urls)
url = urls[0]
for key, value in headers.items():
print (key,' => ',value)
url = "%s|%s='%s'" % (url,key,value)
playUrl(url)
return
添加进去就好了。