vidformer 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
|
|
1
|
+
vidformer.py,sha256=gSe2Kq19Y1v3jQ6cLg6tS7aVr_qB_vN4JcxjCpFXg2k,27989
|
2
|
+
vidformer-0.5.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
3
|
+
vidformer-0.5.2.dist-info/METADATA,sha256=yFb6aI7LrodHg7fvReIQaF760STK5KbfhWEMEHBYxpk,643
|
4
|
+
vidformer-0.5.2.dist-info/RECORD,,
|
vidformer.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"""A Python library for creating and viewing videos with vidformer."""
|
2
2
|
|
3
|
-
__version__ = "0.5.
|
3
|
+
__version__ = "0.5.2"
|
4
4
|
|
5
5
|
import subprocess
|
6
6
|
from fractions import Fraction
|
@@ -77,7 +77,7 @@ class Spec:
|
|
77
77
|
frames.append(frame)
|
78
78
|
return {"frames": frames}, s, f
|
79
79
|
|
80
|
-
def play(self, server, method="html"):
|
80
|
+
def play(self, server, method="html", verbose=False):
|
81
81
|
"""Play the video live in the notebook."""
|
82
82
|
|
83
83
|
spec, sources, filters = self._to_json_spec()
|
@@ -103,7 +103,9 @@ class Spec:
|
|
103
103
|
}
|
104
104
|
arrays = []
|
105
105
|
|
106
|
-
|
106
|
+
if verbose:
|
107
|
+
print(f"Sending to server. Spec is {len(spec_obj_json_gzip_b64)} bytes")
|
108
|
+
|
107
109
|
resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
|
108
110
|
hls_video_url = resp["stream_url"]
|
109
111
|
hls_player_url = resp["player_url"]
|
@@ -150,7 +152,35 @@ class Spec:
|
|
150
152
|
else:
|
151
153
|
return hls_player_url
|
152
154
|
|
153
|
-
def
|
155
|
+
def load(self, server):
|
156
|
+
spec, sources, filters = self._to_json_spec()
|
157
|
+
spec_json_bytes = json.dumps(spec).encode("utf-8")
|
158
|
+
spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
|
159
|
+
spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
|
160
|
+
|
161
|
+
sources = [
|
162
|
+
{
|
163
|
+
"name": s._name,
|
164
|
+
"path": s._path,
|
165
|
+
"stream": s._stream,
|
166
|
+
"service": s._service.as_json() if s._service is not None else None,
|
167
|
+
}
|
168
|
+
for s in sources
|
169
|
+
]
|
170
|
+
filters = {
|
171
|
+
k: {
|
172
|
+
"filter": v._func,
|
173
|
+
"args": v._kwargs,
|
174
|
+
}
|
175
|
+
for k, v in filters.items()
|
176
|
+
}
|
177
|
+
arrays = []
|
178
|
+
|
179
|
+
resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
|
180
|
+
namespace = resp["namespace"]
|
181
|
+
return Loader(server, namespace, self._domain)
|
182
|
+
|
183
|
+
def save(self, server, pth, encoder=None, encoder_opts=None, format=None):
|
154
184
|
"""Save the video to a file."""
|
155
185
|
|
156
186
|
assert encoder is None or type(encoder) == str
|
@@ -191,6 +221,7 @@ class Spec:
|
|
191
221
|
self._fmt,
|
192
222
|
encoder,
|
193
223
|
encoder_opts,
|
224
|
+
format,
|
194
225
|
)
|
195
226
|
|
196
227
|
return resp
|
@@ -273,6 +304,53 @@ class Spec:
|
|
273
304
|
return out
|
274
305
|
|
275
306
|
|
307
|
+
class Loader:
|
308
|
+
def __init__(self, server, namespace: str, domain):
|
309
|
+
self._server = server
|
310
|
+
self._namespace = namespace
|
311
|
+
self._domain = domain
|
312
|
+
|
313
|
+
def _chunk(self, start_i, end_i):
|
314
|
+
return self._server._raw(self._namespace, start_i, end_i)
|
315
|
+
|
316
|
+
def __len__(self):
|
317
|
+
return len(self._domain)
|
318
|
+
|
319
|
+
def _find_index_by_rational(self, value):
|
320
|
+
if value not in self._domain:
|
321
|
+
raise ValueError(f"Rational timestamp {value} is not in the domain")
|
322
|
+
return self._domain.index(value)
|
323
|
+
|
324
|
+
def __getitem__(self, index):
|
325
|
+
if isinstance(index, slice):
|
326
|
+
start = index.start if index.start is not None else 0
|
327
|
+
end = index.stop if index.stop is not None else len(self._domain)
|
328
|
+
assert start >= 0 and start < len(self._domain)
|
329
|
+
assert end >= 0 and end <= len(self._domain)
|
330
|
+
assert start <= end
|
331
|
+
num_frames = end - start
|
332
|
+
all_bytes = self._chunk(start, end - 1)
|
333
|
+
all_bytes_len = len(all_bytes)
|
334
|
+
assert all_bytes_len % num_frames == 0
|
335
|
+
return [
|
336
|
+
all_bytes[
|
337
|
+
i
|
338
|
+
* all_bytes_len
|
339
|
+
// num_frames : (i + 1)
|
340
|
+
* all_bytes_len
|
341
|
+
// num_frames
|
342
|
+
]
|
343
|
+
for i in range(num_frames)
|
344
|
+
]
|
345
|
+
elif isinstance(index, int):
|
346
|
+
assert index >= 0 and index < len(self._domain)
|
347
|
+
return self._chunk(index, index)
|
348
|
+
else:
|
349
|
+
raise TypeError(
|
350
|
+
"Invalid argument type for iloc. Use a slice or an integer."
|
351
|
+
)
|
352
|
+
|
353
|
+
|
276
354
|
class YrdenServer:
|
277
355
|
"""A connection to a Yrden server"""
|
278
356
|
|
@@ -340,7 +418,9 @@ class YrdenServer:
|
|
340
418
|
|
341
419
|
return r.json()
|
342
420
|
|
343
|
-
def _export(
|
421
|
+
def _export(
|
422
|
+
self, pth, spec, sources, filters, arrays, fmt, encoder, encoder_opts, format
|
423
|
+
):
|
344
424
|
req = {
|
345
425
|
"spec": spec,
|
346
426
|
"sources": sources,
|
@@ -352,6 +432,7 @@ class YrdenServer:
|
|
352
432
|
"output_path": pth,
|
353
433
|
"encoder": encoder,
|
354
434
|
"encoder_opts": encoder_opts,
|
435
|
+
"format": format,
|
355
436
|
}
|
356
437
|
|
357
438
|
r = requests.post(f"http://{self._domain}:{self._port}/export", json=req)
|
@@ -360,6 +441,14 @@ class YrdenServer:
|
|
360
441
|
|
361
442
|
return r.json()
|
362
443
|
|
444
|
+
def _raw(self, namespace, start_i, end_i):
|
445
|
+
r = requests.get(
|
446
|
+
f"http://{self._domain}:{self._port}/{namespace}/raw/{start_i}-{end_i}"
|
447
|
+
)
|
448
|
+
if not r.ok:
|
449
|
+
raise Exception(r.text)
|
450
|
+
return r.content
|
451
|
+
|
363
452
|
def hls_js_url(self):
|
364
453
|
"""Return the link to the yrden-hosted hls.js file"""
|
365
454
|
return f"http://{self._domain}:{self._port}/hls.js"
|
@@ -440,6 +529,9 @@ class Source:
|
|
440
529
|
def ts(self):
|
441
530
|
return self._src["ts"]
|
442
531
|
|
532
|
+
def __len__(self):
|
533
|
+
return len(self._src["ts"])
|
534
|
+
|
443
535
|
def __getitem__(self, idx):
|
444
536
|
if type(idx) != Fraction:
|
445
537
|
raise Exception("Source index must be a Fraction")
|
vidformer-0.5.0.dist-info/RECORD
DELETED
@@ -1,4 +0,0 @@
|
|
1
|
-
vidformer.py,sha256=qA5TAoLLhhtWjH9CTu3FfCFK3EKI-R1CapvnTuVSc0A,24944
|
2
|
-
vidformer-0.5.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
3
|
-
vidformer-0.5.0.dist-info/METADATA,sha256=nuIDLRFHysJF8KOhfM_OEx6FtmSr5zVfOkB9lBiMEMs,643
|
4
|
-
vidformer-0.5.0.dist-info/RECORD,,
|
File without changes
|