From c10ffc6d265bfdb55e60c23a3d26e071d7056133 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Thu, 19 Jul 2018 12:24:01 +0200 Subject: [PATCH 01/43] add celery integration --- pod/main/celery.py | 18 ++++++++++++++++++ pod/main/tasks.py | 8 ++++++++ pod/main/templates/aside.html | 2 +- pod/main/templates/base.html | 2 +- pod/main/templates/navbar.html | 2 +- pod/video/encode.py | 16 +++++++++++----- 6 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 pod/main/celery.py create mode 100644 pod/main/tasks.py diff --git a/pod/main/celery.py b/pod/main/celery.py new file mode 100644 index 0000000000..2d22255517 --- /dev/null +++ b/pod/main/celery.py @@ -0,0 +1,18 @@ +import os +from celery import Celery +from django.conf import settings # noqa + +# set the default Django settings module for the 'celery' program. +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pod.settings") + +app = Celery(settings.CELERY_NAME, backend=settings.CELERY_BACKEND, broker=settings.CELERY_BROKER) + +# Using a string here means the worker will not have to +# pickle the object when using Windows. +app.config_from_object('django.conf:settings') +app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) + + +@app.task(bind=True) +def debug_task(self): + print('Request: {0!r}'.format(self.request)) \ No newline at end of file diff --git a/pod/main/tasks.py b/pod/main/tasks.py new file mode 100644 index 0000000000..60298eb20f --- /dev/null +++ b/pod/main/tasks.py @@ -0,0 +1,8 @@ +from celery import shared_task + + +@shared_task(bind=True) +def task_start_encode(self, video_id): + print "START ENCODE VIDEO ID %s" % video_id + from pod.video.encode import encode_video + encode_video(video_id) diff --git a/pod/main/templates/aside.html b/pod/main/templates/aside.html index 04807ae5c9..edddc18ff0 100644 --- a/pod/main/templates/aside.html +++ b/pod/main/templates/aside.html @@ -9,7 +9,7 @@

- G+ + G+

diff --git a/pod/main/templates/base.html b/pod/main/templates/base.html index d7740739a2..b722a3a28a 100644 --- a/pod/main/templates/base.html +++ b/pod/main/templates/base.html @@ -11,7 +11,7 @@ - + diff --git a/pod/main/templates/navbar.html b/pod/main/templates/navbar.html index d8bd570c1f..70acc85cc9 100644 --- a/pod/main/templates/navbar.html +++ b/pod/main/templates/navbar.html @@ -56,7 +56,7 @@ {% if user.is_authenticated %}
  • '; + closebutton += '
  • '; + $("#list-themes").html(closebutton+str).show(); + $(this).parents("li").addClass('list-group-item-info'); return false; }); +$(document).on('click','#close_tab_theme', function() { + $("#list-channels li").removeClass('list-group-item-info'); + $("#list-channels").removeClass("col-8"); + $("#list-channels").addClass("col-12"); + $("#list-themes").html("").hide(); +}); $('#ownerboxnavbar').keyup(function() { if($(this).val() && $(this).val().length > 2) { From ee52c575b22002dc76107076b0d37f950ef58848 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Wed, 8 Aug 2018 11:05:41 +0200 Subject: [PATCH 17/43] remove comments --- pod/main/static/js/main.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/pod/main/static/js/main.js b/pod/main/static/js/main.js index 68af82df55..c5b65d8a59 100644 --- a/pod/main/static/js/main.js +++ b/pod/main/static/js/main.js @@ -113,20 +113,6 @@ var get_list = function(tab, level=0, tab_selected=[], tag_type="option", li_cla /*** CHANNELS IN NAVBAR ***/ $("#list-channels a.show-themes").click(function() { - /* - if($("#list-themes").children().length === 0) { - var str = get_list(listTheme["channel_"+$(this).data('id')], 0, [], tag_type="li", li_class="list-group-item", attrs='', add_link=true, current="", channel=""); - $("#list-channels").removeClass("col-12"); - $("#list-channels").addClass("col-8"); - $("#list-themes").html(str).show(); - $(this).parents("li").addClass('list-group-item-info'); - } else { - $("#list-channels").removeClass("col-8"); - $("#list-channels").addClass("col-12"); - $("#list-themes").html("").hide(); - $(this).parents("li").removeClass('list-group-item-info'); - } - */ $("#list-channels li").removeClass('list-group-item-info'); var str = get_list(listTheme["channel_"+$(this).data('id')], 0, [], tag_type="li", li_class="list-group-item", attrs='', add_link=true, current="", channel=""); $("#list-channels").removeClass("col-12"); @@ -139,6 +125,7 @@ $("#list-channels a.show-themes").click(function() { $(this).parents("li").addClass('list-group-item-info'); return false; }); + $(document).on('click','#close_tab_theme', function() { $("#list-channels li").removeClass('list-group-item-info'); $("#list-channels").removeClass("col-8"); From 955be5ff1af3d6bd2cd9edbb461ead910f1bcef9 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Wed, 8 Aug 2018 14:04:31 +0200 Subject: [PATCH 18/43] add video count and total duration in footer --- pod/main/context_processors.py | 15 +++++++++++++-- pod/main/templates/footer.html | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pod/main/context_processors.py b/pod/main/context_processors.py index b9b1672308..e73644e04e 100644 --- a/pod/main/context_processors.py +++ b/pod/main/context_processors.py @@ -1,8 +1,9 @@ from django.conf import settings as django_settings from django.core.exceptions import ImproperlyConfigured -from django.db.models import Count +from django.db.models import Count, Sum from django.db.models import Prefetch from django.db.models.functions import Substr, Lower +from datetime import timedelta from pod.main.models import LinkFooter @@ -123,10 +124,20 @@ def context_navbar(request): LAST_VIDEOS = get_last_videos() if request.path == "/" else None + list_videos = Video.objects.filter( + encoding_in_progress=False, + is_draft=False) + VIDEOS_COUNT = list_videos.count() + VIDEOS_DURATION = str(timedelta( + seconds=list_videos.aggregate(Sum('duration'))['duration__sum'] + )) + return {'ALL_CHANNELS': all_channels, 'CHANNELS': channels, 'TYPES': types, 'OWNERS': owners, 'DISCIPLINES': disciplines, 'LISTOWNER': json.dumps(listowner), - 'LAST_VIDEOS': LAST_VIDEOS, 'LINK_FOOTER': linkFooter + 'LAST_VIDEOS': LAST_VIDEOS, 'LINK_FOOTER': linkFooter, + 'VIDEOS_COUNT': VIDEOS_COUNT, + 'VIDEOS_DURATION': VIDEOS_DURATION } diff --git a/pod/main/templates/footer.html b/pod/main/templates/footer.html index 87cd5b4bbd..89c2dff1fd 100644 --- a/pod/main/templates/footer.html +++ b/pod/main/templates/footer.html @@ -27,6 +27,6 @@ > {% trans "Pod Project" %}
    -

    {{TITLE_SITE}} {% trans "video platform of" %} {{TITLE_ETB}} - Release {{VERSION}}

    +

    {{TITLE_SITE}} {% trans "video platform of" %} {{TITLE_ETB}} - Release {{VERSION}} - {{VIDEOS_COUNT}} {% trans "videos availables" %} [ {{VIDEOS_DURATION}} ]

    {% endspaceless %} \ No newline at end of file From 02308e538382951e613e694d9c0953c8a0b96216 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Wed, 8 Aug 2018 16:56:27 +0200 Subject: [PATCH 19/43] create video_caption_maker view, template and link it from completion --- .../templates/video_caption_maker.html | 616 ++++++++++++++++++ .../templates/video_completion.html | 7 +- pod/completion/urls.py | 14 +- pod/completion/views.py | 28 +- 4 files changed, 649 insertions(+), 16 deletions(-) create mode 100644 pod/completion/templates/video_caption_maker.html diff --git a/pod/completion/templates/video_caption_maker.html b/pod/completion/templates/video_caption_maker.html new file mode 100644 index 0000000000..021980c2b6 --- /dev/null +++ b/pod/completion/templates/video_caption_maker.html @@ -0,0 +1,616 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load staticfiles %} + +{% block page_extra_head %} + +{% endblock page_extra_head %} + + +{% block breadcrumbs %} + {{block.super}} + + + + +{% endblock %} + +{% block page_title %} +{% trans "Video Caption Maker" %} +{% endblock %} + + +{% block page_content %} +

    {% trans "Video Caption Maker" %}

    + + +

    Load Existing Caption File [optional] :

    + +
    +
    +
    Video:
    + + +
    +
    + +
    +
    +
    + + + + +
    +
    +
    +
    +
    Caption list:
    +
    + +
    +
    + +
    +
    +
    +
    + Select and copy the caption file contents below and paste into a .vtt file: +
    +
    + +
    +
    + + +
    + +
    +
    + + + +{% endblock page_content %} + +{% block collapse_page_aside %} +{% endblock collapse_page_aside %} + +{% block page_aside %} +{% endblock page_aside %} + +{% block more_script %} + +{% endblock more_script %} \ No newline at end of file diff --git a/pod/completion/templates/video_completion.html b/pod/completion/templates/video_completion.html index d9624a6bec..1582f070a6 100644 --- a/pod/completion/templates/video_completion.html +++ b/pod/completion/templates/video_completion.html @@ -139,16 +139,17 @@
     {% trans "Manag

    {% trans 'Subtitle(s) and/or captions(s) related to this video.' %}

    +

    {% trans 'Video Caption Maker' %}

    {% trans 'Several web sites allows you to subtitle or caption videos (for example: Amara)' %}

    {% trans 'You can add several subtitle or caption files to a signle video (for example, in order to subtitle or caption this video in several languages' %}

    {% trans 'Subtitles and/or caption(s) files must be in ".vtt" format.' %}

    {% trans 'You will need the URL of this video to make subtitles and/or captions. This URL is a direct access to this video. Please do not communicate it outside of this site to avoid any misuse.' %}

    -
      +
        {% for vid in video.get_video_mp4 %} -
      • {{vid.name}} :
      • +
      • {{vid.name}} :
      • {% endfor %} {% if video.is_video == False and video.get_video_mp3 %} -
      • {{video.get_video_mp3.name}} :
      • +
      • {{video.get_video_mp3.name}} :
      • {% endif %}
    diff --git a/pod/completion/urls.py b/pod/completion/urls.py index 9521e21f4f..fa8ca0df61 100644 --- a/pod/completion/urls.py +++ b/pod/completion/urls.py @@ -1,14 +1,18 @@ from django.conf.urls import url -from pod.completion.views import video_completion -from pod.completion.views import video_completion_contributor -from pod.completion.views import video_completion_document -from pod.completion.views import video_completion_track -from pod.completion.views import video_completion_overlay +from .views import video_completion +from .views import video_caption_maker +from .views import video_completion_contributor +from .views import video_completion_document +from .views import video_completion_track +from .views import video_completion_overlay urlpatterns = [ url(r'^video_completion/(?P[\-\d\w]+)/$', video_completion, name='video_completion'), + url(r'^video_caption_maker/(?P[\-\d\w]+)/$', + video_caption_maker, + name='video_caption_maker'), url(r'^video_completion_contributor/(?P[\-\d\w]+)/$', video_completion_contributor, name='video_completion_contributor'), diff --git a/pod/completion/views.py b/pod/completion/views.py index 895acec77b..0a80ec5deb 100644 --- a/pod/completion/views.py +++ b/pod/completion/views.py @@ -9,19 +9,31 @@ from django.contrib.admin.views.decorators import staff_member_required from django.core.exceptions import PermissionDenied from pod.video.models import Video -from pod.completion.models import Contributor -from pod.completion.forms import ContributorForm -from pod.completion.models import Document -from pod.completion.forms import DocumentForm -from pod.completion.models import Track -from pod.completion.forms import TrackForm -from pod.completion.models import Overlay -from pod.completion.forms import OverlayForm +from .models import Contributor +from .forms import ContributorForm +from .models import Document +from .forms import DocumentForm +from .models import Track +from .forms import TrackForm +from .models import Overlay +from .forms import OverlayForm import json ACTION = ['new', 'save', 'modify', 'delete'] +@csrf_protect +@staff_member_required(redirect_field_name='referrer') +def video_caption_maker(request, slug): + video = get_object_or_404(Video, slug=slug) + if request.user != video.owner and not request.user.is_superuser: + messages.add_message( + request, messages.ERROR, _(u'You cannot complement this video.')) + raise PermissionDenied + return render( + request, + 'video_caption_maker.html', + {'video': video}) @csrf_protect @login_required(redirect_field_name='referrer') From 41c62181fd4283a11192ef2190cb4b886c9984c2 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Thu, 9 Aug 2018 10:30:20 +0200 Subject: [PATCH 20/43] add copy to clipboard button --- pod/completion/templates/video_caption_maker.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pod/completion/templates/video_caption_maker.html b/pod/completion/templates/video_caption_maker.html index 021980c2b6..315e7c7e65 100644 --- a/pod/completion/templates/video_caption_maker.html +++ b/pod/completion/templates/video_caption_maker.html @@ -167,7 +167,7 @@

    {% trans "Video Caption Maker" %}

    -
    @@ -606,11 +606,14 @@

    {% trans "Video Caption Maker" %}

    } } } - appendCurrentCaption(); - SortAndDisplayCaptionList(); } - +$("#copyToClipboard").on('click', function() { + var copyText = document.getElementById("captionFile"); + copyText.select(); + document.execCommand("copy"); + alert("text copied, paste it in vtt file"); +}); {% endblock more_script %} \ No newline at end of file From f644e66482c9f503f536f2af01fb7d412413577f Mon Sep 17 00:00:00 2001 From: ptitloup Date: Thu, 9 Aug 2018 11:20:12 +0200 Subject: [PATCH 21/43] add some style and fix bug with start is 0 --- .../templates/video_caption_maker.html | 64 +++++++------------ 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/pod/completion/templates/video_caption_maker.html b/pod/completion/templates/video_caption_maker.html index 315e7c7e65..c891844048 100644 --- a/pod/completion/templates/video_caption_maker.html +++ b/pod/completion/templates/video_caption_maker.html @@ -7,16 +7,12 @@ #videoElm { display: block; border: solid 1px #999; - -moz-box-sizing: border-box; - box-sizing: border-box; width: 100%; min-height: 297px; } .videoError { display: block; background-color: #999; - -moz-box-sizing: border-box; - box-sizing: border-box; width: 100%; min-height: 297px; color: white; @@ -33,8 +29,6 @@ } #textCaptionEntry { - -moz-box-sizing: border-box; - box-sizing: border-box; width: 100%; height: auto; line-height: 19px; @@ -61,8 +55,6 @@ #display { border: solid 1px #999; height: 374px; - -moz-box-sizing: border-box; - box-sizing: border-box; overflow: auto; } @@ -94,7 +86,6 @@ #display div span:nth-child(3) { font-style: italic; } - {% endblock page_extra_head %} @@ -122,12 +113,12 @@

    {% trans "Video Caption Maker" %}

    -

    Load Existing Caption File [optional] :

    +

    {% trans "Load Existing Caption File [optional]" %} :

    -
    Video:
    + {% trans "Video" %}:
    -
    - - - - -
    + + + +
    -
    Caption list:
    + {% trans "Caption list" %}:
    -
    - +
    +
    - Select and copy the caption file contents below and paste into a .vtt file: + {% trans "Select and copy the caption file contents below and paste into a .vtt file" %}:
    - - + + +
    - -
    - - - + {% endblock page_content %} @@ -213,12 +198,14 @@

    {% trans "Video Caption Maker" %}

    }); $("#clearAllCaptions").on('click', function () { - captionsArray.length = 0; - autoPauseAtTime = -1; - $("#display div").remove(); - $("#captionTitle").html(" "); - $("#textCaptionEntry").val(""); - $("#captionFormatNone").click(); + var deleteConfirm = confirm(gettext("Are you sure you want to delete all caption ?")); + if (deleteConfirm){ + captionsArray.length = 0; + autoPauseAtTime = -1; + $("#display div").remove(); + $("#captionTitle").html(" "); + $("#textCaptionEntry").val(""); + } }); // index into captionsArray of the caption being displayed. -1 if none. @@ -464,16 +451,13 @@

    {% trans "Video Caption Maker" %}

    function DisplayVTTSource() { var s = "WEBVTT\r\n\r\n"; - for (var i = 0; i < captionsArray.length; ++i) { if (captionsArray[i].caption != "") { s += (FormatTime(captionsArray[i].start) + " --> " + FormatTime(captionsArray[i].end) + "\r\n"); s += captionsArray[i].caption + "\r\n\r\n"; } } - $("#captionFile").val(s); - $("#captionFileKind").text(".vtt"); } var captionFileSourceUpdateTimer = null; @@ -521,7 +505,6 @@

    {% trans "Video Caption Maker" %}

    } $("#ttFile").get(0).addEventListener("change", function() { - alert('coucou'); var filesObject = $("#ttFile").get(0).files; if (filesObject && filesObject.length > 0) { LoadCaptionFile(filesObject[0]); @@ -591,6 +574,7 @@

    {% trans "Video Caption Maker" %}

    if (timeMatch) { appendCurrentCaption(); cueStart = ParseTime(timeMatch[1]); + if(cueStart==0) cueStart = "0.0"; cueEnd = ParseTime(timeMatch[2]); continue; } From 99316e39f902e885fdd9962fa396a0bb3aabfa5a Mon Sep 17 00:00:00 2001 From: ptitloup Date: Thu, 9 Aug 2018 11:21:53 +0200 Subject: [PATCH 22/43] pep8 --- pod/completion/views.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pod/completion/views.py b/pod/completion/views.py index 0a80ec5deb..60488b6f1d 100644 --- a/pod/completion/views.py +++ b/pod/completion/views.py @@ -22,6 +22,7 @@ ACTION = ['new', 'save', 'modify', 'delete'] + @csrf_protect @staff_member_required(redirect_field_name='referrer') def video_caption_maker(request, slug): @@ -31,9 +32,10 @@ def video_caption_maker(request, slug): request, messages.ERROR, _(u'You cannot complement this video.')) raise PermissionDenied return render( - request, - 'video_caption_maker.html', - {'video': video}) + request, + 'video_caption_maker.html', + {'video': video}) + @csrf_protect @login_required(redirect_field_name='referrer') From d540a8581b6bb2685648fd260c6f984c1ec83f42 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Thu, 9 Aug 2018 14:55:18 +0200 Subject: [PATCH 23/43] improve encoding module to get better log, database info and send email only if debug is false --- pod/video/encode.py | 111 +++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/pod/video/encode.py b/pod/video/encode.py index c0caccdf4d..508326eb20 100644 --- a/pod/video/encode.py +++ b/pod/video/encode.py @@ -138,12 +138,9 @@ def change_encoding_step(video_id, num_step, desc): def add_encoding_log(video_id, log): - encoding_log, created = EncodingLog.objects.get_or_create( + encoding_log = EncodingLog.objects.get( video=Video.objects.get(id=video_id)) - if encoding_log.log: - encoding_log.log += "\n\n%s" % log - else: - encoding_log.log = "\n\n%s" % log + encoding_log.log += "\n\n%s" % (log) encoding_log.save() if DEBUG: print(log) @@ -162,23 +159,36 @@ def check_file(path_file): def encode_video(video_id): start = "Start at : %s" % time.ctime() - change_encoding_step(video_id, 0, "start") - add_encoding_log(video_id, start) - video_to_encode = Video.objects.get(id=video_id) video_to_encode.encoding_in_progress = True video_to_encode.save() + change_encoding_step(video_id, 0, "start") - if check_file(video_to_encode.video.path): + encoding_log, created = EncodingLog.objects.get_or_create( + video=Video.objects.get(id=video_id)) + encoding_log.log = "%s" % start + encoding_log.save() + + if check_file(video_to_encode.video.path): change_encoding_step(video_id, 1, "remove old data") remove_msg = remove_old_data(video_id) add_encoding_log(video_id, "remove old data : %s" % remove_msg) - change_encoding_step(video_id, 2, "get video data") + # create video dir + change_encoding_step(video_id, 2, "create output dir") + output_dir = create_outputdir(video_id, video_to_encode.video.path) + add_encoding_log(video_id, "output_dir : %s" % output_dir) + + # clear log file + open(output_dir + "/encoding.log", 'w').close() + with open(output_dir + "/encoding.log", "a") as f: + f.write("%s\n" % start) + + change_encoding_step(video_id, 3, "get video data") video_data = {} try: - video_data = get_video_data(video_id) + video_data = get_video_data(video_id, output_dir) add_encoding_log(video_id, "get video data : %s" % video_data["msg"]) except ValueError: @@ -192,11 +202,6 @@ def encode_video(video_id): video_to_encode.duration = video_data["duration"] video_to_encode.save() - # create video dir - change_encoding_step(video_id, 3, "create output dir") - output_dir = create_outputdir(video_id, video_to_encode.video.path) - add_encoding_log(video_id, "output_dir : %s" % output_dir) - if video_data["is_video"]: # encodage_video # create encoding video command @@ -357,6 +362,11 @@ def encode_video(video_id): video_to_encode.encoding_in_progress = False video_to_encode.save() + # End + add_encoding_log(video_id, "End : %s" % time.ctime()) + with open(output_dir + "/encoding.log", "a") as f: + f.write("\n\nEnd : %s" % time.ctime()) + # envois mail fin encodage if EMAIL_ON_ENCODING_COMPLETION: send_email_encoding(video_to_encode) @@ -374,7 +384,7 @@ def encode_video(video_id): # ########################################################################## -def get_video_data(video_id): +def get_video_data(video_id, output_dir): video_to_encode = Video.objects.get(id=video_id) msg = "" source = "%s" % video_to_encode.video.path @@ -383,15 +393,18 @@ def get_video_data(video_id): ffproberesult = subprocess.run( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - msg += "\nffprobe command : %s" % command + msg += "\nffprobe command : \n- %s\n" % command """ add_encoding_log( video_id, "command : %s \n ffproberesult : %s" % (command, ffproberesult)) """ info = json.loads(ffproberesult.stdout.decode('utf-8')) - msg += "%s" % json.dumps( - info, sort_keys=True, indent=4, separators=(',', ': ')) + with open(output_dir + "/encoding.log", "a") as f: + f.write('\n\ffprobe commande video result :\n\n') + f.write('%s\n' % json.dumps( + info, sort_keys=True, indent=4, separators=(',', ': '))) + is_video = False contain_audio = False in_height = 0 @@ -426,8 +439,12 @@ def get_video_data(video_id): "command : %s \n ffproberesult : %s" % (command, ffproberesult)) """ info = json.loads(ffproberesult.stdout.decode('utf-8')) - msg += "%s" % json.dumps( - info, sort_keys=True, indent=4, separators=(',', ': ')) + # msg += "%s" % json.dumps( + # info, sort_keys=True, indent=4, separators=(',', ': ')) + with open(output_dir + "/encoding.log", "a") as f: + f.write('\n\ffprobe commande audio result :\n\n') + f.write('%s\n' % json.dumps( + info, sort_keys=True, indent=4, separators=(',', ': '))) if len(info["streams"]) > 0: contain_audio = True @@ -510,15 +527,15 @@ def encode_video_mp4(source, cmd, output_dir): ffmpegMp4Command = "%s %s -i %s %s" % ( FFMPEG, FFMPEG_MISC_PARAMS, source, cmd) - msg = "ffmpegMp4Command :\n%s" % ffmpegMp4Command - msg += "Encoding Mp4 : %s" % time.ctime() + msg = "\nffmpegMp4Command :\n%s" % ffmpegMp4Command + msg += "\n- Encoding Mp4 : %s" % time.ctime() # ffmpegvideo = subprocess.getoutput(ffmpegMp4Command) ffmpegvideo = subprocess.run( ffmpegMp4Command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - msg += "End Encoding Mp4 : %s" % time.ctime() + msg += "\n- End Encoding Mp4 : %s" % time.ctime() with open(output_dir + "/encoding.log", "ab") as f: f.write(b'\n\nffmpegvideoMP4:\n\n') @@ -646,7 +663,7 @@ def encode_video_mp3(video_id, source, output_dir): 'output_dir': output_dir, 'audio_bitrate': AUDIO_BITRATE } - msg = "ffmpegMP3Command :\n%s" % command + msg = "\nffmpegMP3Command :\n%s" % command msg += "\n- Encoding MP3 : %s" % time.ctime() # ffmpegaudio = subprocess.getoutput(command) ffmpegaudio = subprocess.run( @@ -738,15 +755,15 @@ def encode_video_playlist(source, cmd, output_dir): ffmpegPlaylistCommand = "%s %s -i %s %s" % ( FFMPEG, FFMPEG_MISC_PARAMS, source, cmd) - msg = "ffmpegPlaylistCommand :\n%s" % ffmpegPlaylistCommand - msg += "Encoding Playlist : %s" % time.ctime() + msg = "\nffmpegPlaylistCommand :\n%s" % ffmpegPlaylistCommand + msg += "\n- Encoding Playlist : %s" % time.ctime() # ffmpegvideo = subprocess.getoutput(ffmpegPlaylistCommand) ffmpegvideo = subprocess.run( ffmpegPlaylistCommand, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - msg += "End Encoding Playlist : %s" % time.ctime() + msg += "\n- End Encoding Playlist : %s" % time.ctime() with open(output_dir + "/encoding.log", "ab") as f: f.write(b'\n\nffmpegvideoPlaylist:\n\n') @@ -1026,11 +1043,6 @@ def remove_old_data(video_id): video_to_encode.overview = None video_to_encode.save() - encoding_log, created = EncodingLog.objects.get_or_create( - video=Video.objects.get(id=video_id)) - encoding_log.log = "" - encoding_log.save() - encoding_log_msg = "" encoding_log_msg += remove_previous_encoding_video( video_to_encode) @@ -1115,22 +1127,25 @@ def send_email_encoding(video_to_encode): 'content_id': video_to_encode.id } ) - message = "%s\n\n%s\n%s\n" % ( + message = "%s\n%s\n\n%s\n%s\n%s\n" % ( + _("Hello"), _(u"The content “%(content_title)s” has been encoded to Web " + "formats, and is now available on %(site_title)s.") % { 'content_title': video_to_encode.title, 'site_title': TITLE_SITE }, _(u"You will find it here:"), - content_url + content_url, + _("Regards") ) from_email = HELP_MAIL to_email = [] to_email.append(video_to_encode.owner.email) html_message = "" - html_message = '

    %s

    %s
    %s\ -

    ' % ( + html_message = '

    %s

    %s

    %s
    %s\ +

    %s

    ' % ( + _("Hello"), _(u"The content “%(content_title)s” has been encoded to Web " + "formats, and is now available on %(site_title)s.") % { 'content_title': '%s' % video_to_encode.title, @@ -1138,16 +1153,18 @@ def send_email_encoding(video_to_encode): }, _(u"You will find it here:"), content_url, - content_url - ) - send_mail( - subject, - message, - from_email, - to_email, - fail_silently=False, - html_message=html_message, + content_url, + _("Regards") ) + if not DEBUG: + send_mail( + subject, + message, + from_email, + to_email, + fail_silently=False, + html_message=html_message, + ) mail_managers( subject, message, fail_silently=False, html_message=html_message) From 31e198bcff7871a5a696795a077d9f533c65df27 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Fri, 10 Aug 2018 10:13:41 +0200 Subject: [PATCH 24/43] add chapter in import data --- pod/video/encode.py | 1 - pod/video/management/commands/import_data.py | 68 ++++++++++++++------ 2 files changed, 50 insertions(+), 19 deletions(-) mode change 100644 => 100755 pod/video/encode.py diff --git a/pod/video/encode.py b/pod/video/encode.py old mode 100644 new mode 100755 index 508326eb20..ae832f8b55 --- a/pod/video/encode.py +++ b/pod/video/encode.py @@ -169,7 +169,6 @@ def encode_video(video_id): encoding_log.log = "%s" % start encoding_log.save() - if check_file(video_to_encode.video.path): change_encoding_step(video_id, 1, "remove old data") remove_msg = remove_old_data(video_id) diff --git a/pod/video/management/commands/import_data.py b/pod/video/management/commands/import_data.py index 2544b62232..656b47e2f8 100755 --- a/pod/video/management/commands/import_data.py +++ b/pod/video/management/commands/import_data.py @@ -4,6 +4,7 @@ from django.conf import settings from django.apps import apps from pod.video.models import Video +from django.core.exceptions import ObjectDoesNotExist try: from pod.authentication.models import Owner except ImportError: @@ -17,12 +18,15 @@ BASE_DIR = getattr( settings, 'BASE_DIR', '/home/pod/django_projects/podv2/pod') +VIDEO_ID_TO_EXCLUDE = getattr( + settings, 'VIDEO_ID_TO_EXCLUDE', []) + class Command(BaseCommand): - args = 'Channel Theme Type User Discipline' + args = 'Channel Theme Type User Discipline Pod tags Chapter' help = 'Import from V1' valid_args = ['Channel', 'Theme', 'Type', 'User', 'Discipline', 'FlatPage', - 'UserProfile', 'Pod', 'tags'] + 'UserProfile', 'Pod', 'tags', 'Chapter'] def add_arguments(self, parser): parser.add_argument('import') @@ -39,21 +43,10 @@ def handle(self, *args, **options): with open(filepath, "r") as infile: if type_to_import in ('Channel', 'Theme', 'Type', 'User', 'Discipline', 'FlatPage', 'UserProfile', - 'Pod'): + 'Pod', 'Chapter'): data = serializers.deserialize("json", infile) for obj in data: - if AUTHENTICATION and type_to_import == 'UserProfile': - owner = Owner.objects.get( - user_id=obj.object.user_id) - owner.auth_type = obj.object.auth_type - owner.affiliation = obj.object.affiliation - owner.commentaire = obj.object.commentaire - # todo image - owner.save() - else: - print(obj, obj.object.id) - obj.object.headband = None - obj.save() + self.save_object(type_to_import, obj) if type_to_import in ('tags'): data = json.load(infile) for obj in data: @@ -63,6 +56,27 @@ def handle(self, *args, **options): "******* Warning: you must give some arguments: %s *******" % self.valid_args) + def save_object(self, type_to_import, obj): + if AUTHENTICATION and type_to_import == 'UserProfile': + owner = Owner.objects.get( + user_id=obj.object.user_id) + owner.auth_type = obj.object.auth_type + owner.affiliation = obj.object.affiliation + owner.commentaire = obj.object.commentaire + # todo image + owner.save() + else: + print(obj, obj.object.id, obj.object.video.id) + if (type_to_import == 'Pod' + and obj.object.id in VIDEO_ID_TO_EXCLUDE): + print(obj.object.id, " are exclude") + else: + if obj.object.video.id not in VIDEO_ID_TO_EXCLUDE: + obj.object.headband = None + obj.save() + else: + print("video ", obj.object.video.id, " are exclude") + def migrate_to_v2(self, filepath, type_to_import): f = open(filepath, 'r') filedata = f.read() @@ -92,12 +106,23 @@ def get_new_data(self, type_to_import, filedata): "pods.pod", "video.video" ) + if type_to_import == 'Chapter': + newdata = filedata.replace( + "pods.chapterpods", + "chapter.chapter" + ).replace( + "\"time\"", + "\"time_start\"" + ) return newdata def add_tag_to_video(self, video_id, list_tag): - video = Video.objects.get(id=video_id) - video.tags = ', '.join(list_tag) - video.save() + try: + video = Video.objects.get(id=video_id) + video.tags = ', '.join(list_tag) + video.save() + except ObjectDoesNotExist: + print(video_id, " does not exist") """ @@ -113,6 +138,8 @@ def add_tag_to_video(self, video_id, list_tag): from django.contrib.auth.models import User from django.contrib.flatpages.models import FlatPage +from pods.models import ChapterPods + from django.core import serializers jsonserializer = serializers.get_serializer("json") json_serializer = jsonserializer() @@ -167,6 +194,11 @@ def add_tag_to_video(self, video_id, list_tag): with open("tags.json", "w") as out: out.write(json.dumps(list_tag, indent=2)) + +with open("Chapter.json", "w") as out: + json_serializer.serialize(ChapterPods.objects.all().order_by('video'), + indent=2, stream=out) + # todo 'chapter', 'completion', From f0f31481cd0178398a07f110bda9201a8b37e08e Mon Sep 17 00:00:00 2001 From: ptitloup Date: Fri, 10 Aug 2018 14:54:02 +0200 Subject: [PATCH 25/43] improve import data and add completion contributor and document --- pod/video/management/commands/import_data.py | 184 ++++++++++++++++--- 1 file changed, 155 insertions(+), 29 deletions(-) diff --git a/pod/video/management/commands/import_data.py b/pod/video/management/commands/import_data.py index 656b47e2f8..4c415d01bf 100755 --- a/pod/video/management/commands/import_data.py +++ b/pod/video/management/commands/import_data.py @@ -4,7 +4,10 @@ from django.conf import settings from django.apps import apps from pod.video.models import Video +from pod.completion.models import Document from django.core.exceptions import ObjectDoesNotExist +from django.core.files import File + try: from pod.authentication.models import Owner except ImportError: @@ -12,6 +15,15 @@ # from django.contrib.auth.models import User as Owner import os import json +import wget + +if getattr(settings, 'USE_PODFILE', False): + FILEPICKER = True + from pod.podfile.models import CustomFileModel + from pod.podfile.models import UserFolder +else: + FILEPICKER = False + from pod.main.models import CustomFileModel AUTHENTICATION = True if apps.is_installed('pod.authentication') else False @@ -21,12 +33,15 @@ VIDEO_ID_TO_EXCLUDE = getattr( settings, 'VIDEO_ID_TO_EXCLUDE', []) +FROM_URL = getattr(settings, 'FROM_URL', "https://pod.univ-lille1.fr/media/") + class Command(BaseCommand): - args = 'Channel Theme Type User Discipline Pod tags Chapter' + args = 'Channel Theme Type User Discipline Pod tags Chapter Contributor...' help = 'Import from V1' valid_args = ['Channel', 'Theme', 'Type', 'User', 'Discipline', 'FlatPage', - 'UserProfile', 'Pod', 'tags', 'Chapter'] + 'UserProfile', 'Pod', 'tags', 'Chapter', 'Contributor', + 'Overlay', 'docpods'] def add_arguments(self, parser): parser.add_argument('import') @@ -43,14 +58,15 @@ def handle(self, *args, **options): with open(filepath, "r") as infile: if type_to_import in ('Channel', 'Theme', 'Type', 'User', 'Discipline', 'FlatPage', 'UserProfile', - 'Pod', 'Chapter'): + 'Pod', 'Chapter', 'Contributor', + 'Overlay'): data = serializers.deserialize("json", infile) for obj in data: self.save_object(type_to_import, obj) - if type_to_import in ('tags'): + if type_to_import in ('tags', 'docpods'): data = json.load(infile) for obj in data: - self.add_tag_to_video(obj, data[obj]) + self.add_data_to_video(type_to_import, obj, data[obj]) else: print( "******* Warning: you must give some arguments: %s *******" @@ -86,36 +102,88 @@ def migrate_to_v2(self, filepath, type_to_import): f.write(newdata) f.close() + def Channel(self, filedata): + return filedata.replace( + "pods.channel", + "video.channel" + ) + + def Theme(self, filedata): + return filedata.replace( + "pods.theme", + "video.theme" + ) + + def Type(self, filedata): + return filedata.replace( + "pods.type", + "video.type" + ).replace("headband", "icon") + + def Discipline(self, filedata): + return filedata.replace( + "pods.discipline", + "video.discipline" + ).replace("headband", "icon") + + def Pod(self, filedata): + return filedata.replace( + "pods.pod", + "video.video" + ) + + def Chapter(self, filedata): + return filedata.replace( + "pods.chapterpods", + "chapter.chapter" + ).replace( + "\"time\"", + "\"time_start\"" + ) + + def Contributor(self, filedata): + return filedata.replace( + "pods.contributorpods", + "completion.contributor" + ) + + def Overlay(self, filedata): + return filedata.replace( + "pods.overlaypods", + "completion.overlay" + ) + def get_new_data(self, type_to_import, filedata): newdata = "" - if type_to_import in ('Channel', 'Theme', 'Type', 'Discipline'): - newdata = filedata.replace( - "pods." + type_to_import.lower(), - "video." + type_to_import.lower() - ) - if type_to_import in ('Type', 'Discipline'): - newdata = newdata.replace("headband", "icon") - if type_to_import in ('User', 'FlatPage', 'tags'): + type_import = { + "Channel": self.Channel, + "Theme": self.Theme, + "Type": self.Type, + "Discipline": self.Discipline, + "Pod": self.Pod, + "Chapter": self.Chapter, + "Contributor": self.Contributor, + "Overlay": self.Overlay, + } + if type_import.get(type_to_import): + func = type_import.get(type_to_import) + return func(filedata) + + if type_to_import in ('User', 'FlatPage', 'tags', 'docpods'): newdata = filedata if type_to_import == 'UserProfile': newdata = filedata.replace( "core.userprofile", "authentication.owner" ).replace("\"image\":", "\"userpicture\":") - if type_to_import == 'Pod': - newdata = filedata.replace( - "pods.pod", - "video.video" - ) - if type_to_import == 'Chapter': - newdata = filedata.replace( - "pods.chapterpods", - "chapter.chapter" - ).replace( - "\"time\"", - "\"time_start\"" - ) + return newdata + def add_data_to_video(self, type_to_import, obj, data): + if type_to_import in ('docpods',): + self.add_doc_to_video(obj, data) + if type_to_import in ('tags',): + self.add_tag_to_video(obj, data) + def add_tag_to_video(self, video_id, list_tag): try: video = Video.objects.get(id=video_id) @@ -124,6 +192,55 @@ def add_tag_to_video(self, video_id, list_tag): except ObjectDoesNotExist: print(video_id, " does not exist") + def add_doc_to_video(self, video_id, list_doc): + print(video_id, list_doc) + try: + video = Video.objects.get(id=video_id) + for doc in list_doc: + new_file = self.download_doc(doc) + print("\n", new_file) + document = self.create_and_save_doc(new_file, video) + Document.objects.create(video=video, document=document) + except ObjectDoesNotExist: + print(video_id, " does not exist") + + def download_doc(self, doc): + source_url = FROM_URL + doc + dest_file = os.path.join( + settings.MEDIA_ROOT, + 'tempfile', + os.path.basename(doc) + ) + os.makedirs(os.path.dirname(dest_file), exist_ok=True) + new_file = wget.download(source_url, dest_file) + return new_file + + def create_and_save_doc(self, new_file, video): + if FILEPICKER: + homedir, created = UserFolder.objects.get_or_create( + name='home', + owner=video.owner) + videodir, created = UserFolder.objects.get_or_create( + name='%s' % video.slug, + owner=video.owner) + document = CustomFileModel( + folder=videodir, + created_by=video.owner + ) + document.file.save( + os.path.basename(new_file), + File(open(new_file, "rb")), + save=True) + document.save() + else: + document = CustomFileModel() + document.file.save( + os.path.basename(new_file), + File(open(new_file, "rb")), + save=True) + document.save() + return document + """ SAVE FROM PODV1 @@ -139,6 +256,7 @@ def add_tag_to_video(self, video_id, list_tag): from django.contrib.flatpages.models import FlatPage from pods.models import ChapterPods +from pods.models import ContributorPods from django.core import serializers jsonserializer = serializers.get_serializer("json") @@ -199,8 +317,16 @@ def add_tag_to_video(self, video_id, list_tag): json_serializer.serialize(ChapterPods.objects.all().order_by('video'), indent=2, stream=out) -# todo -'chapter', -'completion', +with open("Contributor.json", "w") as out: + json_serializer.serialize(ContributorPods.objects.all().order_by('video'), + indent=2, stream=out) + +list_doc = {} +for p in Pod.objects.all(): + list_doc["%s" %p.id] = [] + for d in p.docpods_set.all(): + list_doc["%s" %p.id].append(d.document.file.name) +with open("docpods.json", "w") as out: + out.write(json.dumps(list_doc, indent=2)) """ From c294053b61bbce0b487a57ee0eed76029b8459da Mon Sep 17 00:00:00 2001 From: ptitloup Date: Fri, 10 Aug 2018 16:47:59 +0200 Subject: [PATCH 26/43] add import data for tracks, update webvtt, fix bug in template --- pod/main/templates/navbar.html | 2 +- pod/video/management/commands/import_data.py | 79 +++++++++++++++++-- pod/video/templates/videos/video-element.html | 2 +- pod/video/templates/videos/video-info.html | 2 +- requirements.txt | 4 +- 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/pod/main/templates/navbar.html b/pod/main/templates/navbar.html index 70acc85cc9..5b94ce6c94 100644 --- a/pod/main/templates/navbar.html +++ b/pod/main/templates/navbar.html @@ -43,7 +43,7 @@ -
    + diff --git a/pod/video/management/commands/import_data.py b/pod/video/management/commands/import_data.py index 4c415d01bf..7f4876cbf4 100755 --- a/pod/video/management/commands/import_data.py +++ b/pod/video/management/commands/import_data.py @@ -4,7 +4,7 @@ from django.conf import settings from django.apps import apps from pod.video.models import Video -from pod.completion.models import Document +from pod.completion.models import Document, Track from django.core.exceptions import ObjectDoesNotExist from django.core.files import File @@ -16,6 +16,8 @@ import os import json import wget +import webvtt +import codecs if getattr(settings, 'USE_PODFILE', False): FILEPICKER = True @@ -41,7 +43,7 @@ class Command(BaseCommand): help = 'Import from V1' valid_args = ['Channel', 'Theme', 'Type', 'User', 'Discipline', 'FlatPage', 'UserProfile', 'Pod', 'tags', 'Chapter', 'Contributor', - 'Overlay', 'docpods'] + 'Overlay', 'docpods', 'trackpods'] def add_arguments(self, parser): parser.add_argument('import') @@ -63,7 +65,7 @@ def handle(self, *args, **options): data = serializers.deserialize("json", infile) for obj in data: self.save_object(type_to_import, obj) - if type_to_import in ('tags', 'docpods'): + if type_to_import in ('tags', 'docpods', 'trackpods'): data = json.load(infile) for obj in data: self.add_data_to_video(type_to_import, obj, data[obj]) @@ -154,7 +156,7 @@ def Overlay(self, filedata): ) def get_new_data(self, type_to_import, filedata): - newdata = "" + newdata = filedata type_import = { "Channel": self.Channel, "Theme": self.Theme, @@ -168,9 +170,6 @@ def get_new_data(self, type_to_import, filedata): if type_import.get(type_to_import): func = type_import.get(type_to_import) return func(filedata) - - if type_to_import in ('User', 'FlatPage', 'tags', 'docpods'): - newdata = filedata if type_to_import == 'UserProfile': newdata = filedata.replace( "core.userprofile", "authentication.owner" @@ -183,6 +182,8 @@ def add_data_to_video(self, type_to_import, obj, data): self.add_doc_to_video(obj, data) if type_to_import in ('tags',): self.add_tag_to_video(obj, data) + if type_to_import in ('trackpods',): + self.add_track_to_video(obj, data) def add_tag_to_video(self, video_id, list_tag): try: @@ -204,6 +205,56 @@ def add_doc_to_video(self, video_id, list_doc): except ObjectDoesNotExist: print(video_id, " does not exist") + def add_track_to_video(self, video_id, list_doc): + print(video_id, list_doc) + try: + video = Video.objects.get(id=video_id) + for doc in list_doc: + new_file = self.download_doc(doc["src"]) + print("\n", new_file) + fname, dot, extension = new_file.rpartition('.') + if extension == "srt": + new_file = self.convert_to_vtt(new_file) + else: + if extension != "vtt": + print("************ WARNING !!!!! ************") + print(video_id, list_doc) + print("************ ************") + new_file = "" + if new_file != "": + document = self.create_and_save_doc(new_file, video) + Track.objects.create(video=video, src=document, + kind=doc["kind"], lang=doc["lang"]) + except ObjectDoesNotExist: + print(video_id, " does not exist") + + def convert_to_vtt(self, new_file): + try: + webvtt.from_srt(new_file).save(new_file[:-3] + "vtt") + new_file = new_file[:-3] + "vtt" + return new_file + except UnicodeDecodeError: + print("************ codecs ***********") + with codecs.open(new_file, + "r", + encoding="latin-1") as sourceFile: + with codecs.open(new_file[:-3] + "txt", + "w", + "utf-8") as targetFile: + contents = sourceFile.read() + targetFile.write(contents) + webvtt.from_srt( + new_file[:-3] + "txt").save(new_file[:-3] + "vtt") + new_file = new_file[:-3] + "vtt" + return new_file + except webvtt.errors.MalformedFileError: + print("************ " + "The file does not have a valid format. !!!!! " + "************") + print(new_file) + print("************ ************") + return "" + def download_doc(self, doc): source_url = FROM_URL + doc dest_file = os.path.join( @@ -329,4 +380,18 @@ def create_and_save_doc(self, new_file, video): with open("docpods.json", "w") as out: out.write(json.dumps(list_doc, indent=2)) +list_track = {} +for p in Pod.objects.all(): + if p.trackpods_set.all().count() > 0: + list_track["%s" %p.id] = [] + for d in p.trackpods_set.all(): + if d.src : + data = {} + data['kind'] = d.kind + data['lang'] = d.lang + data['src'] = d.src.file.name + list_track["%s" %p.id].append(data) +with open("trackpods.json", "w") as out: + out.write(json.dumps(list_track, indent=2)) + """ diff --git a/pod/video/templates/videos/video-element.html b/pod/video/templates/videos/video-element.html index a36d97fbb7..4b8feb973d 100644 --- a/pod/video/templates/videos/video-element.html +++ b/pod/video/templates/videos/video-element.html @@ -7,7 +7,7 @@

    {% for track in video.track_set.all%} - + {%endfor%} diff --git a/pod/video/templates/videos/video-info.html b/pod/video/templates/videos/video-info.html index 9debd747aa..1e33cec214 100644 --- a/pod/video/templates/videos/video-info.html +++ b/pod/video/templates/videos/video-info.html @@ -13,7 +13,7 @@
     {% trans 'Summary' %} {% if tag_list %}

    {% trans 'Tags' %}:  {% for tag in tag_list %} - + {{ tag }} {% endfor %} diff --git a/requirements.txt b/requirements.txt index f57e063469..fe47acbfef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ django-ckeditor==5.3.1 Pillow==5.1.0 django-tagging==0.4.6 django-modeltranslation==0.12.2 -webvtt-py==0.4.1 +webvtt-py==0.4.2 django-cas-sso==1.1.7 ldap3==2.5 django-progressbarupload==0.1.7 @@ -15,4 +15,4 @@ django-filter==1.1.0 sorl-thumbnail==12.4.1 django-lti-provider==0.3.3 django-auth-mixins==1.0.1 -celery==4.2.1 \ No newline at end of file +celery==4.2.1 From 929454bd4c81c4bf65d8fa199c5c597e04e2be3b Mon Sep 17 00:00:00 2001 From: ptitloup Date: Mon, 13 Aug 2018 13:48:17 +0200 Subject: [PATCH 27/43] add import data for enrichment --- pod/video/management/commands/import_data.py | 90 +++++++++++++++++++- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/pod/video/management/commands/import_data.py b/pod/video/management/commands/import_data.py index 7f4876cbf4..68d855a6bc 100755 --- a/pod/video/management/commands/import_data.py +++ b/pod/video/management/commands/import_data.py @@ -5,6 +5,7 @@ from django.apps import apps from pod.video.models import Video from pod.completion.models import Document, Track +from pod.enrichment.models import Enrichment from django.core.exceptions import ObjectDoesNotExist from django.core.files import File @@ -21,7 +22,7 @@ if getattr(settings, 'USE_PODFILE', False): FILEPICKER = True - from pod.podfile.models import CustomFileModel + from pod.podfile.models import CustomFileModel, CustomImageModel from pod.podfile.models import UserFolder else: FILEPICKER = False @@ -43,7 +44,7 @@ class Command(BaseCommand): help = 'Import from V1' valid_args = ['Channel', 'Theme', 'Type', 'User', 'Discipline', 'FlatPage', 'UserProfile', 'Pod', 'tags', 'Chapter', 'Contributor', - 'Overlay', 'docpods', 'trackpods'] + 'Overlay', 'docpods', 'trackpods', 'enrichpods'] def add_arguments(self, parser): parser.add_argument('import') @@ -65,10 +66,15 @@ def handle(self, *args, **options): data = serializers.deserialize("json", infile) for obj in data: self.save_object(type_to_import, obj) - if type_to_import in ('tags', 'docpods', 'trackpods'): + if type_to_import in ( + 'tags', 'docpods', 'trackpods', 'enrichpods'): data = json.load(infile) for obj in data: - self.add_data_to_video(type_to_import, obj, data[obj]) + if int(obj) not in VIDEO_ID_TO_EXCLUDE: + self.add_data_to_video( + type_to_import, + obj, + data[obj]) else: print( "******* Warning: you must give some arguments: %s *******" @@ -184,6 +190,8 @@ def add_data_to_video(self, type_to_import, obj, data): self.add_tag_to_video(obj, data) if type_to_import in ('trackpods',): self.add_track_to_video(obj, data) + if type_to_import in ('enrichpods',): + self.add_enrich_to_video(obj, data) def add_tag_to_video(self, video_id, list_tag): try: @@ -255,6 +263,33 @@ def convert_to_vtt(self, new_file): print("************ ************") return "" + def add_enrich_to_video(self, video_id, list_doc): + print(video_id) + try: + video = Video.objects.get(id=video_id) + for doc in list_doc: + image = None + if doc["type"] == "image" and doc["image"] != "": + new_file = self.download_doc(doc["image"]) + image = self.create_and_save_image( + new_file, video) if new_file != "" else None + document = None + if doc["type"] == "document" and doc["document"] != "": + new_file = self.download_doc(doc["document"]) + document = self.create_and_save_doc( + new_file, video) if new_file != "" else None + + Enrichment.objects.create( + video=video, title=doc["title"], + stop_video=doc["stop_video"], start=doc["start"], + end=doc["end"], type=doc["type"], image=image, + document=document, richtext=doc["richtext"], + weblink=doc["weblink"], embed=doc["embed"] + ) + + except ObjectDoesNotExist: + print(video_id, " does not exist") + def download_doc(self, doc): source_url = FROM_URL + doc dest_file = os.path.join( @@ -292,6 +327,32 @@ def create_and_save_doc(self, new_file, video): document.save() return document + def create_and_save_image(self, new_file, video): + if FILEPICKER: + homedir, created = UserFolder.objects.get_or_create( + name='home', + owner=video.owner) + videodir, created = UserFolder.objects.get_or_create( + name='%s' % video.slug, + owner=video.owner) + image = CustomImageModel( + folder=videodir, + created_by=video.owner + ) + image.file.save( + os.path.basename(new_file), + File(open(new_file, "rb")), + save=True) + image.save() + else: + image = CustomFileModel() + image.file.save( + os.path.basename(new_file), + File(open(new_file, "rb")), + save=True) + image.save() + return image + """ SAVE FROM PODV1 @@ -394,4 +455,25 @@ def create_and_save_doc(self, new_file, video): with open("trackpods.json", "w") as out: out.write(json.dumps(list_track, indent=2)) +list_enrich = {} +for p in Pod.objects.all().order_by('id'): + if p.enrichpods_set.all().count() > 0: + list_enrich["%s" %p.id] = [] + for d in p.enrichpods_set.all(): + data = {} + data['title'] = d.title + data['stop_video'] = d.stop_video + data['start'] = d.start + data['end'] = d.end + data['type'] = d.type + data['image'] = d.image.file.name if d.image else "" + data['richtext'] = d.richtext + data['weblink'] = d.weblink + data['document'] = d.document.file.name if d.document else "" + data['embed'] = d.embed + list_enrich["%s" %p.id].append(data) + +with open("enrichpods.json", "w") as out: + out.write(json.dumps(list_enrich, indent=2)) + """ From 9bdb7edaf0b17aaff3eb1dc6c0e7114c943fe156 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Mon, 13 Aug 2018 16:49:32 +0200 Subject: [PATCH 28/43] change the display of the video information --- pod/video/templates/videos/video.html | 242 +++++++++++++++++++++++++- pod/video/templatetags/video_tags.py | 2 +- 2 files changed, 240 insertions(+), 4 deletions(-) diff --git a/pod/video/templates/videos/video.html b/pod/video/templates/videos/video.html index 6225dce53e..a8db0d7b6d 100644 --- a/pod/video/templates/videos/video.html +++ b/pod/video/templates/videos/video.html @@ -100,16 +100,244 @@

    {{theme.title}}

    {% include 'playlist/playlist_player.html' with playlist=playlist %} {% endif %} - {% include 'videos/video-element.html' %} +

    +{% if video.licence %}{% endif %} {{video.title|title}} +{% if video.date_evt %}[{{ video.date_evt }}]{% endif %} + + + +

    + +
    + + + {%endif%} {% endblock video-element %} {% endblock page_content %} @@ -203,4 +435,8 @@
    {% if not form %} {% include 'videos/video-script.html'%} {% endif %} + + {% endblock more_script %} diff --git a/pod/video/templatetags/video_tags.py b/pod/video/templatetags/video_tags.py index f6242b9025..2a19096eec 100644 --- a/pod/video/templatetags/video_tags.py +++ b/pod/video/templatetags/video_tags.py @@ -19,7 +19,7 @@ def get_app_link(video, app): url = reverse('%(app)s:video_%(app)s' % {"app": app}, kwargs={'slug': video.slug}) return ('%(link)s') % { + 'class="dropdown-item" target="_blank">%(link)s') % { "app": app, "url": url, "link": _('%s' % app)} From ec20fe19266d162fd17fb201fb06bd4cfee5fe33 Mon Sep 17 00:00:00 2001 From: ptitloup Date: Mon, 13 Aug 2018 17:03:40 +0200 Subject: [PATCH 29/43] move video information into video-info.html, fix display in iframe --- pod/video/templates/videos/video-iframe.html | 19 +- pod/video/templates/videos/video-info.html | 189 +++++++--------- pod/video/templates/videos/video.html | 221 +------------------ 3 files changed, 93 insertions(+), 336 deletions(-) diff --git a/pod/video/templates/videos/video-iframe.html b/pod/video/templates/videos/video-iframe.html index 014064ed17..ef9cc0d4a1 100644 --- a/pod/video/templates/videos/video-iframe.html +++ b/pod/video/templates/videos/video-iframe.html @@ -50,18 +50,14 @@ border-radius: 1%; border: 1px #ccc solid; box-shadow: 0 0 10px rgba(50, 50, 50, 0.95); - padding: 5px; + padding: 1.25rem; /*margin:5%;*/ - background-color: rgba(50, 50, 50, 0.50) !important; + /*background-color: rgba(50, 50, 50, 0.50) !important;*/ overflow: auto; z-index:1000; } .list-group-item { - background-color: rgba(50, 50, 50, 0.50) !important; - } - .scrollspy-video { - padding:10px; - background-color: rgba(220, 220, 220, 0.70); + /*background-color: rgba(50, 50, 50, 0.50) !important;*/ } .close { margin:10px; @@ -82,7 +78,7 @@ {% include 'videos/video-element.html' %} {% endblock video-element %} -