Example #1
0
def annotate_topic_tree(node, level=0, statusdict=None, remote_sizes=None, lang_code=None):
    # Not needed when on an api request (since translation.activate is already called),
    #   but just to do things right / in an encapsulated way...
    # Though to be honest, this isn't quite right; we should be DE-activating translation
    #   at the end.  But with so many function exit-points... just a nightmare.

    if not lang_code:
        lang_code = settings.LANGUAGE_CODE

    if level == 0:
        translation.activate(lang_code)

    if not statusdict:
        statusdict = {}

    if node["kind"] == "Topic":
        if "Video" not in node["contains"]:
            return None

        children = []
        unstarted = True
        complete = True

        for child_node in node["children"]:
            child = annotate_topic_tree(child_node, level=level + 1, statusdict=statusdict, lang_code=lang_code)
            if not child:
                continue
            elif child["addClass"] == "unstarted":
                complete = False
            elif child["addClass"] == "partial":
                complete = False
                unstarted = False
            elif child["addClass"] == "complete":
                unstarted = False
            children.append(child)

        if not children:
            # All children were eliminated; so eliminate self.
            return None

        return {
            "title": _(node["title"]),
            "tooltip": re.sub(r'<[^>]*?>', '', _(node.get("description")) or ""),
            "isFolder": True,
            "key": node["id"],
            "children": children,
            "addClass": complete and "complete" or unstarted and "unstarted" or "partial",
            "expand": level < 1,
        }

    elif node["kind"] == "Video":
        video_id = node.get("youtube_id", node.get("id"))
        youtube_id = get_youtube_id(video_id, lang_code=lang_code)

        if not youtube_id:
            # This video doesn't exist in this language, so remove from the topic tree.
            return None

        # statusdict contains an item for each video registered in the database
        # will be {} (empty dict) if there are no videos downloaded yet
        percent = statusdict.get(youtube_id, 0)
        vid_size = None
        status = None

        if not percent:
            status = "unstarted"
            vid_size = get_remote_video_size(youtube_id) / float(2 ** 20)  # express in MB
        elif percent == 100:
            status = "complete"
            vid_size = get_local_video_size(youtube_id, 0) / float(2 ** 20)  # express in MB
        else:
            status = "partial"

        return {
            "title": _(node["title"]),
            "tooltip": re.sub(r'<[^>]*?>', '', _(node.get("description")) or ""),
            "key": youtube_id,
            "addClass": status,
            "size": vid_size,
        }

    return None
Example #2
0
def annotate_topic_tree(node,
                        level=0,
                        statusdict=None,
                        remote_sizes=None,
                        lang_code=settings.LANGUAGE_CODE):
    # Not needed when on an api request (since translation.activate is already called),
    #   but just to do things right / in an encapsulated way...
    # Though to be honest, this isn't quite right; we should be DE-activating translation
    #   at the end.  But with so many function exit-points... just a nightmare.
    if level == 0:
        translation.activate(lang_code)

    if not statusdict:
        statusdict = {}

    if node["kind"] == "Topic":
        if "Video" not in node["contains"]:
            return None

        children = []
        unstarted = True
        complete = True

        for child_node in node["children"]:
            child = annotate_topic_tree(child_node,
                                        level=level + 1,
                                        statusdict=statusdict,
                                        lang_code=lang_code)
            if not child:
                continue
            elif child["addClass"] == "unstarted":
                complete = False
            elif child["addClass"] == "partial":
                complete = False
                unstarted = False
            elif child["addClass"] == "complete":
                unstarted = False
            children.append(child)

        if not children:
            # All children were eliminated; so eliminate self.
            return None

        return {
            "title": _(node["title"]),
            "tooltip": re.sub(r'<[^>]*?>', '',
                              _(node.get("description")) or ""),
            "isFolder": True,
            "key": node["id"],
            "children": children,
            "addClass": complete and "complete" or unstarted and "unstarted"
            or "partial",
            "expand": level < 1,
        }

    elif node["kind"] == "Video":
        video_id = node.get("youtube_id", node.get("id"))
        youtube_id = get_youtube_id(video_id, lang_code=lang_code)

        if not youtube_id:
            # This video doesn't exist in this language, so remove from the topic tree.
            return None

        # statusdict contains an item for each video registered in the database
        # will be {} (empty dict) if there are no videos downloaded yet
        percent = statusdict.get(youtube_id, 0)
        vid_size = None
        status = None

        if not percent:
            status = "unstarted"
            vid_size = get_remote_video_size(youtube_id) / float(
                2**20)  # express in MB
        elif percent == 100:
            status = "complete"
            vid_size = get_local_video_size(youtube_id, 0) / float(
                2**20)  # express in MB
        else:
            status = "partial"

        return {
            "title": _(node["title"]),
            "tooltip": re.sub(r'<[^>]*?>', '',
                              _(node.get("description")) or ""),
            "key": youtube_id,
            "addClass": status,
            "size": vid_size,
        }

    return None
Example #3
0
def stamp_availability_on_video(video, format="mp4", force=False, stamp_urls=True, videos_path=None):
    """
    Stamp all relevant urls and availability onto a video object (if necessary), including:
    * whether the video is available (on disk or online)
    """
    videos_path = videos_path or settings.CONTENT_ROOT

    def compute_video_availability(youtube_id, format, videos_path=videos_path):
        return {"on_disk": is_video_on_disk(youtube_id, format, videos_path=videos_path)}

    def compute_video_metadata(youtube_id, format):
        return {"stream_type": "video/%s" % format}

    def compute_video_urls(youtube_id, format, lang_code, on_disk=None, thumb_formats=["png", "jpg"], videos_path=videos_path):
        if on_disk is None:
            on_disk = is_video_on_disk(youtube_id, format, videos_path=videos_path)

        if on_disk:
            video_base_url = settings.CONTENT_URL + youtube_id
            stream_url = video_base_url + ".%s" % format
            thumbnail_url = None  # default to None now, so we know when no thumbnail is available.

            for thumb_format in thumb_formats:  # find the thumbnail on disk
                thumb_filename = '%s.%s' % (youtube_id, thumb_format)
                thumb_filepath = os.path.join(videos_path, thumb_filename)
                if os.path.exists(thumb_filepath):
                    thumbnail_url = video_base_url + "." + thumb_format  # default
                    break

        elif settings.BACKUP_VIDEO_SOURCE and lang_code == "en":
            dict_vals = {"youtube_id": youtube_id, "video_format": format, "thumb_format": thumb_formats[0] }
            stream_url = settings.BACKUP_VIDEO_SOURCE % dict_vals
            thumbnail_url = settings.BACKUP_THUMBNAIL_SOURCE % dict_vals if settings.BACKUP_THUMBNAIL_SOURCE else None

        else:
            return {}  # no URLs
        return {"stream": stream_url, "thumbnail": thumbnail_url}

    video_availability = video.get("availability", {}) if not force else {}
    en_youtube_id = get_youtube_id(video["id"], lang_code=None)  # get base ID
    video_map = get_id2oklang_map(video["id"]) or {}

    if not "on_disk" in video_availability:
        for lang_code in video_map.keys():
            youtube_id = video_map[lang_code].encode('utf-8')
            video_availability[lang_code] = compute_video_availability(youtube_id, format=format, videos_path=videos_path)
        video_availability["en"] = video_availability.get("en", {"on_disk": False})  # en should always be defined

        # Summarize status
        any_on_disk = any([lang_avail["on_disk"] for lang_avail in video_availability.values()])
        any_available = any_on_disk or bool(settings.BACKUP_VIDEO_SOURCE)

    if stamp_urls:
        # Loop over all known dubbed videos
        for lang_code, youtube_id in video_map.iteritems():
            urls = compute_video_urls(youtube_id, format, lang_code, on_disk=video_availability[lang_code]["on_disk"], videos_path=videos_path)
            if urls:
                # Only add properties if anything is available.
                video_availability[lang_code].update(urls)
                video_availability[lang_code].update(compute_video_metadata(youtube_id, format))

        # Get the (english) subtitle urls
        subtitle_lang_codes = get_langs_with_subtitle(en_youtube_id)
        subtitles_tuple = [(lc, get_srt_url(en_youtube_id, lc)) for lc in subtitle_lang_codes if os.path.exists(get_srt_path(lc, en_youtube_id))]
        subtitles_urls = dict(subtitles_tuple)
        video_availability["en"]["subtitles"] = subtitles_urls

    # now scrub any values that don't actually exist
    for lang_code in video_availability.keys():
        if not video_availability[lang_code]["on_disk"] and len(video_availability[lang_code]) == 1:
            del video_availability[lang_code]

    # Now summarize some availability onto the video itself
    video["availability"] = video_availability
    video["on_disk"]   = any_on_disk
    video["available"] = any_available

    return video
Example #4
0
def stamp_availability_on_video(video, format="mp4", force=False, stamp_urls=True, videos_path=None):
    """
    Stamp all relevant urls and availability onto a video object (if necessary), including:
    * whether the video is available (on disk or online)
    """
    videos_path = videos_path or settings.CONTENT_ROOT

    def compute_video_availability(youtube_id, format, videos_path=videos_path):
        return {"on_disk": is_video_on_disk(youtube_id, format, videos_path=videos_path)}

    def compute_video_metadata(youtube_id, format):
        return {"stream_type": "video/%s" % format}

    def compute_video_urls(youtube_id, format, lang_code, on_disk=None, thumb_formats=["png", "jpg"], videos_path=videos_path):
        if on_disk is None:
            on_disk = is_video_on_disk(youtube_id, format, videos_path=videos_path)

        if on_disk:
            video_base_url = settings.CONTENT_URL + youtube_id
            stream_url = video_base_url + ".%s" % format
            thumbnail_url = None  # default to None now, so we know when no thumbnail is available.

            for thumb_format in thumb_formats:  # find the thumbnail on disk
                thumb_filename = '%s.%s' % (youtube_id, thumb_format)
                thumb_filepath = os.path.join(videos_path, thumb_filename)
                if os.path.exists(thumb_filepath):
                    thumbnail_url = video_base_url + "." + thumb_format  # default
                    break

        elif settings.BACKUP_VIDEO_SOURCE and lang_code == "en":
            dict_vals = {"youtube_id": youtube_id, "video_format": format, "thumb_format": thumb_formats[0] }
            stream_url = settings.BACKUP_VIDEO_SOURCE % dict_vals
            thumbnail_url = settings.BACKUP_THUMBNAIL_SOURCE % dict_vals if settings.BACKUP_THUMBNAIL_SOURCE else None

        else:
            return {}  # no URLs
        return {"stream": stream_url, "thumbnail": thumbnail_url}

    video_availability = video.get("availability", {}) if not force else {}
    en_youtube_id = get_youtube_id(video["id"], lang_code=None)  # get base ID
    video_map = get_id2oklang_map(video["id"]) or {}

    if not "on_disk" in video_availability:
        for lang_code in video_map.keys():
            youtube_id = video_map[lang_code].encode('utf-8')
            video_availability[lang_code] = compute_video_availability(youtube_id, format=format, videos_path=videos_path)
        video_availability["en"] = video_availability.get("en", {"on_disk": False})  # en should always be defined

        # Summarize status
        any_on_disk = any([lang_avail["on_disk"] for lang_avail in video_availability.values()])
        any_available = any_on_disk or bool(settings.BACKUP_VIDEO_SOURCE)

    if stamp_urls:
        # Loop over all known dubbed videos
        for lang_code, youtube_id in video_map.iteritems():
            urls = compute_video_urls(youtube_id, format, lang_code, on_disk=video_availability[lang_code]["on_disk"], videos_path=videos_path)
            if urls:
                # Only add properties if anything is available.
                video_availability[lang_code].update(urls)
                video_availability[lang_code].update(compute_video_metadata(youtube_id, format))

        # Get the (english) subtitle urls
        subtitle_lang_codes = get_langs_with_subtitle(en_youtube_id)
        subtitles_tuple = [(lc, get_srt_url(en_youtube_id, lc)) for lc in subtitle_lang_codes if os.path.exists(get_srt_path(lc, en_youtube_id))]
        subtitles_urls = dict(subtitles_tuple)
        video_availability["en"]["subtitles"] = subtitles_urls

    # now scrub any values that don't actually exist
    for lang_code in video_availability.keys():
        if not video_availability[lang_code]["on_disk"] and len(video_availability[lang_code]) == 1:
            del video_availability[lang_code]

    # Now summarize some availability onto the video itself
    video["availability"] = video_availability
    video["on_disk"]   = any_on_disk
    video["available"] = any_available

    return video