1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
-- TODO prefetch if next in playlist?
-- TODO handle torrent with multiple video files (if webtorrent can print json)
-- - don't close kill webtorrent while still videos unplayed? or in playlist?
-- - store titles/info when starting webtorrent and check stream-open-filename
-- for any item in playlist to see if it matches stored entry
local settings = {
close_webtorrent = true,
remove_files = true,
download_directory = "/tmp/webtorrent",
webtorrent_flags = "",
webtorrent_verbosity = "speed"
}
(require "mp.options").read_options(settings, "webtorrent-hook")
local open_videos = {}
-- http://lua-users.org/wiki/StringRecipes
local function ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
-- https://stackoverflow.com/questions/132397/get-back-the-output-of-os-execute-in-lua
function os.capture(cmd, decolorize, raw)
if decolorize then
-- https://github.com/webtorrent/webtorrent-cli/issues/132
-- TODO webtorrent should have a way to just print json information with
-- no colors
-- https://stackoverflow.com/questions/19296667/remove-ansi-color-codes-from-a-text-file-using-bash/30938702#30938702
cmd = cmd .. " | sed -r 's/\\x1B\\[(([0-9]{1,2})?(;)?([0-9]{1,2})?)?[m,K,H,f,J]//g'"
end
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
if raw then return s end
s = string.gsub(s, '^%s+', '')
s = string.gsub(s, '%s+$', '')
-- s = string.gsub(s, '[\n\r]+', ' ')
return s
end
function read_file(file)
local fh = assert(io.open(file, "rb"))
local contents = fh:read("*all")
fh:close()
return contents
end
function play_torrent()
local url = mp.get_property("stream-open-filename")
if (url:find("magnet:") == 1 or url:find("peerflix://") == 1
or url:find("webtorrent://") == 1 or ends_with(url, "torrent")) then
if url:find("webtorrent://") == 1 then
url = url:sub(14)
end
if url:find("peerflix://") == 1 then
url = url:sub(12)
end
os.execute("mkdir -p " .. settings.download_directory)
-- don't reuse files (so multiple mpvs works)
local output_file = settings.download_directory
.. "/webtorrent-output-" .. mp.get_time() .. ".log"
-- --keep-seeding is to prevent webtorrent from quitting once the download
-- is done
local webtorrent_command = "webtorrent "
.. settings.webtorrent_flags
.. " --out '" .. settings.download_directory .. "' --keep-seeding \""
.. url .. "\" > " .. output_file .. " 2>&1 & echo $!"
mp.msg.info("Starting webtorrent server")
mp.msg.info(webtorrent_command)
local pid = os.capture(webtorrent_command)
mp.msg.info("Waiting for webtorrent server")
local url_command = "tail -f " .. output_file
.. " | awk '/Server running at:/ {print $4; exit}'"
local url = os.capture(url_command, true)
mp.msg.info("Webtorrent server is up")
local title_command = "awk '/(Seeding|Downloading): / "
.. "{gsub(/(Seeding|Downloading): /, \"\"); print; exit}' "
.. output_file
local title = os.capture(title_command, true)
mp.msg.info("Setting media title to: " .. title)
mp.set_property("force-media-title", title)
local path
if title then
path = settings.download_directory .. "/\"" .. title .. "\""
end
open_videos[url] = {title=title,path=path,pid=pid}
mp.set_property("stream-open-filename", url)
if settings.webtorrent_verbosity == "speed" then
local printer_pid
local printer_pid_file = settings.download_directory
.. "/webtorrent-printer-" .. mp.get_time() .. ".pid"
os.execute("tail -f " .. output_file
.. " | awk '/Speed:/' ORS='\r' & echo -n $! > "
.. printer_pid_file)
printer_pid = read_file(printer_pid_file)
mp.register_event("file-loaded",
function()
os.execute("kill " .. printer_pid)
end
)
end
end
end
function webtorrent_cleanup()
local url = mp.get_property("stream-open-filename")
if settings.close_webtorrent and open_videos[url] then
local title = open_videos[url].title
local path = open_videos[url].path
local pid = open_videos[url].pid
if pid then
mp.msg.info("Closing webtorrent for " .. title .. " with pid " .. pid)
os.execute("kill " .. pid)
end
if settings.remove_files then
if path then
mp.msg.info("Removing media file for " .. title .. " with path " .. path)
os.execute("rm -r " .. path)
end
end
open_videos[url] = {}
end
end
mp.add_hook("on_load", 50, play_torrent)
mp.add_hook("on_unload", 10, webtorrent_cleanup)
|