From 8f84d317641e44d1fd9cbf9a56c1ef8a905a32cd Mon Sep 17 00:00:00 2001 From: Roland Date: Tue, 15 Oct 2019 14:36:02 -0600 Subject: [PATCH] Adding captions module for videos. --- TODO.md | 2 + requirements.txt | 1 - test/example.en.vtt | 48 +++++++++++++++++++ .../plugins/example_plugin/requirements.txt | 1 + wrolpi/plugins/videos/api.py | 1 + wrolpi/plugins/videos/captions.py | 20 ++++++++ wrolpi/plugins/videos/requirements.txt | 2 + wrolpi/plugins/videos/test/test_captions.py | 30 ++++++++++++ wrolpi/web.py | 2 +- 9 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 test/example.en.vtt create mode 100644 wrolpi/plugins/example_plugin/requirements.txt create mode 100755 wrolpi/plugins/videos/captions.py create mode 100644 wrolpi/plugins/videos/requirements.txt create mode 100644 wrolpi/plugins/videos/test/test_captions.py diff --git a/TODO.md b/TODO.md index 2e1982ea..f52f06e5 100644 --- a/TODO.md +++ b/TODO.md @@ -14,3 +14,5 @@ Code TODO ========= 1. Example plugin based off videos plugin 1. Check that videos can be removed or renamed + 1. Plugin has support for systemd so it can start it's own service + 1. Plugin has support for cronjobs diff --git a/requirements.txt b/requirements.txt index 52a84dda..8a416403 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,5 +6,4 @@ Jinja2>=2.10.1 mock>=3.0.5 psycopg2-binary>=2.8.3 pyyaml>=5.1.2 -youtube-dl>=2019.8.13 pytest>=5.2.1 \ No newline at end of file diff --git a/test/example.en.vtt b/test/example.en.vtt new file mode 100644 index 00000000..fb0fb9b2 --- /dev/null +++ b/test/example.en.vtt @@ -0,0 +1,48 @@ +WEBVTT +Kind: captions +Language: en + +00:00:00.000 --> 00:00:05.269 align:start position:0% + +okay<00:00:01.310> welcome<00:00:02.310> to<00:00:02.429> this<00:00:02.550> session<00:00:04.130> this<00:00:05.130> is + +00:00:05.269 --> 00:00:05.279 align:start position:0% +okay welcome to this session this is + + +00:00:05.279 --> 00:00:07.760 align:start position:0% +okay welcome to this session this is +called<00:00:05.879> the<00:00:05.970> kinetic<00:00:06.420> bunny<00:00:06.690> need<00:00:07.319> to<00:00:07.529> meet + +00:00:07.760 --> 00:00:07.770 align:start position:0% +called the kinetic bunny need to meet + + +00:00:07.770 --> 00:00:11.450 align:start position:0% +called the kinetic bunny need to meet +the<00:00:07.890> virtual<00:00:08.280> bonnie<00:00:08.519> emilio<00:00:09.380> stop<00:00:10.380> this<00:00:11.340> is + +00:00:11.450 --> 00:00:11.460 align:start position:0% +the virtual bonnie emilio stop this is + + +00:00:11.460 --> 00:00:15.410 align:start position:0% +the virtual bonnie emilio stop this is +jana<00:00:11.639> car<00:00:11.880> who<00:00:13.700> just<00:00:14.700> to<00:00:14.759> give<00:00:14.940> a<00:00:14.969> little<00:00:15.030> bit + +00:00:15.410 --> 00:00:15.420 align:start position:0% +jana car who just to give a little bit + + +00:00:15.420 --> 00:00:18.859 align:start position:0% +jana car who just to give a little bit +of<00:00:15.529> background<00:00:16.529> information<00:00:17.390> we<00:00:18.390> come<00:00:18.630> from<00:00:18.750> a + +00:00:18.859 --> 00:00:18.869 align:start position:0% +of background information we come from a + + +00:00:18.869 --> 00:00:21.109 align:start position:0% +of background information we come from a +company<00:00:19.109> called<00:00:19.199> le<00:00:19.529> code<00:00:19.740> from<00:00:20.550> finland<00:00:20.939> and + diff --git a/wrolpi/plugins/example_plugin/requirements.txt b/wrolpi/plugins/example_plugin/requirements.txt new file mode 100644 index 00000000..359beeff --- /dev/null +++ b/wrolpi/plugins/example_plugin/requirements.txt @@ -0,0 +1 @@ +# Add your pip requirements here \ No newline at end of file diff --git a/wrolpi/plugins/videos/api.py b/wrolpi/plugins/videos/api.py index 7404c15c..04c451ce 100644 --- a/wrolpi/plugins/videos/api.py +++ b/wrolpi/plugins/videos/api.py @@ -71,6 +71,7 @@ def json_statuses_streamer(func): '{"success": "stream-complete"}\n' """ + @wraps(func) def wrap(*a, **kw): yield from (json.dumps({'status': i}) + '\n' for i in func(*a, **kw)) yield json.dumps({'success': 'stream-complete'}) + '\n' diff --git a/wrolpi/plugins/videos/captions.py b/wrolpi/plugins/videos/captions.py new file mode 100755 index 00000000..393db240 --- /dev/null +++ b/wrolpi/plugins/videos/captions.py @@ -0,0 +1,20 @@ +#! /usr/bin/env python3 +from typing import Generator + +import webvtt + + +def get_caption_text(vtt_path: str) -> Generator: + for caption in webvtt.read(vtt_path): + text = str(caption.text).strip() + yield text + + +def get_unique_caption_lines(vtt_path: str) -> Generator: + last_line = None + for text in get_caption_text(vtt_path): + for line in text.split('\n'): + if line and line != last_line: + last_line = line + yield line + diff --git a/wrolpi/plugins/videos/requirements.txt b/wrolpi/plugins/videos/requirements.txt new file mode 100644 index 00000000..33f8ee2c --- /dev/null +++ b/wrolpi/plugins/videos/requirements.txt @@ -0,0 +1,2 @@ +youtube-dl>=2019.8.13 +webvtt-py==0.4.2 \ No newline at end of file diff --git a/wrolpi/plugins/videos/test/test_captions.py b/wrolpi/plugins/videos/test/test_captions.py new file mode 100644 index 00000000..455ee3ee --- /dev/null +++ b/wrolpi/plugins/videos/test/test_captions.py @@ -0,0 +1,30 @@ +import unittest + +from wrolpi.plugins.videos import captions + + +class TestCaption(unittest.TestCase): + + def test_example_en_vtt(self): + vtt_path = 'test/example.en.vtt' + + expected = ['okay welcome to this session this is', + 'okay welcome to this session this is', + 'okay welcome to this session this is\ncalled the kinetic bunny need to meet', + 'called the kinetic bunny need to meet', + 'called the kinetic bunny need to meet\nthe virtual bonnie emilio stop this is', + 'the virtual bonnie emilio stop this is', + 'the virtual bonnie emilio stop this is\njana car who just to give a little bit', + 'jana car who just to give a little bit', + 'jana car who just to give a little bit\nof background information we come from a', + 'of background information we come from a', + 'of background information we come from a\ncompany called le code from finland and'] + self.assertEqual(list(captions.get_caption_text(vtt_path)), expected) + + expected = ['okay welcome to this session this is', + 'called the kinetic bunny need to meet', + 'the virtual bonnie emilio stop this is', + 'jana car who just to give a little bit', + 'of background information we come from a', + 'company called le code from finland and'] + self.assertEqual(list(captions.get_unique_caption_lines(vtt_path)), expected) diff --git a/wrolpi/web.py b/wrolpi/web.py index a0189400..11debb98 100644 --- a/wrolpi/web.py +++ b/wrolpi/web.py @@ -21,7 +21,7 @@ ROOT_CONFIG = { class ClientRoot(object): def __init__(self): - # Install plugins defined in plugins.plugins + # Install plugins defined in user_plugins for name, plugin in PLUGINS.items(): setattr(self, name, plugin.ClientRoot())