-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstreaming.py
96 lines (78 loc) · 2.93 KB
/
streaming.py
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
#
# skaer media streamer
# Copyright (c) 2019 Emil Penchev
#
# Project page:
# http://skaermedia.org
#
# licensed under GNU GPL version 3 (or later)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
import cherrypy
import requests
import db_utils
import contextlib
import uuid
class Streamer(object):
""" Stream various media sources. """
_obj_instance = None
@staticmethod
def instance():
if not Streamer._obj_instance:
Streamer._obj_instance = Streamer()
return Streamer._obj_instance
def __init__(self):
self._init_db()
def _init_db(self):
self._db = db_utils.Sqlite("file::memory:?cache=shared", in_mem=True)
self._db.execute("CREATE TABLE urlmap(_id varchar(32), url varchar(255))")
def attach_url(self, url):
"""
Map a streaming url to a unique reference id.
"""
_id = str(uuid.uuid3(uuid.NAMESPACE_URL, url).hex)
self._db.execute("INSERT INTO urlmap VALUES(?, ?)", (_id, url))
return _id
def detach_url(self, _id):
self._db.execute("DELETE FROM urlmap where _id=?", (_id,))
def get_url(self, _id):
result = self._db.execute("SELECT url FROM urlmap where _id=?", (_id,))
url = result[0][0]
return url
@cherrypy.expose
def index(self, **kwargs):
range_header = None
if 'Range' in cherrypy.request.headers:
range_header = {'Range' : cherrypy.request.headers['Range']}
stream_url = self.get_url(kwargs['id'])
resp = requests.get(stream_url, headers=range_header, stream=True)
if resp.status_code != requests.codes.ok:
resp.raise_for_status()
# If not in download mode trasmit media streaming headers.
if not kwargs.get('download', False):
cherrypy.response.headers.update(resp.headers)
else:
cherrypy.response.headers.update({'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename=\"test.mp3\"'})
def content(resp):
for chunk in resp.iter_content(chunk_size=8192):
yield chunk
resp.close()
# TODO detach url when done
return content(resp)
index._cp_config = {'response.stream': True}
@cherrypy.expose
def download(self):
pass