예제 #1
0
    def publish(self, channeltitle, url, title=""):
        """Publish the video (channeltitle, url, title)
        """
        adminuser = get_user('coco')
        try:
            channel = Channel.objects.get(Q(slug=channeltitle) | Q(title=channeltitle))
        except:
            channel = Channel(creator=adminuser, contributor=adminuser, title=channeltitle, slug=slugify(channeltitle))
            channel.save()

        if not title:
            title = os.path.basename(url)
        slug = slugify(title)
        try:
            chapter = Chapter.objects.get(title=title, channel=channel)
        except Chapter.DoesNotExist:
            chapter = Chapter(creator=adminuser, contributor=adminuser, channel=channel, title=title, slug=slug)
            chapter.save()

        activity = Activity(creator=adminuser, contributor=adminuser,
                            title=title,
                            slug=slug,
                            chapter=chapter)
        activity.save()

        # Get length
        duration = 0
        dur = subprocess.check_output('gst-discoverer-1.0 "%s" | grep Duration' % url, shell=True)
        if dur:
            info = re.search('(\d+):(\d+):(\d+.\d+)', dur)
            if info:
                duration = float(info.group(1)) * 24 * 60 + float(info.group(2)) * 60 + float(info.group(3))

        vid = Video(creator=adminuser, contributor=adminuser,
                    activity=activity,
                    title=title,
                    url=url,
                    slug=slug,
                    duration=duration)

        # Save anyway, so that we have a valid video even if thumbnailing fails
        vid.save()
        # Get thumbnail
        thumbnail_name = os.tmpnam() + ".jpg"
        # Low-dependency thumbnailer
        subprocess.call('gst-launch-1.0 gnlurisource "uri=%s" start=4000000 duration=2000000 ! videoconvert ! jpegenc ! filesink location=%s' % (url, thumbnail_name), shell=True)
        if os.path.exists(thumbnail_name):
            with open(thumbnail_name, 'rb') as f:
                vid.thumbnail.save(os.path.basename(thumbnail_name), File(f))
            for o in (vid.activity, vid.activity.chapter, vid.activity.chapter.channel):
                if not o.thumbnail:
                    # Use same thumbnail
                    with open(thumbnail_name, 'rb') as f:
                        o.thumbnail.save(os.path.basename(thumbnail_name), File(f))
                        o.save()
            os.unlink(thumbnail_name)
        vid.save()
예제 #2
0
    def _info(self, channel, info):
        """Import video/channel info from info.json files. Params: channel_title info.json
        """
        with open(info, 'r') as f:
            data = json.load(f)
        self.stdout.write("Saving %s\n" % data.get("title"))

        adminuser = get_user('coco')
        dirname = os.path.dirname(os.path.abspath(info))
        try:
            c = Channel.objects.get(Q(title=channel) | Q(slug=channel))
        except Channel.DoesNotExist:
            c = Channel(creator=adminuser, contributor=adminuser, title=channel, slug=slugify(channel))
            c.save()

        title = data.get("title", "Titre inconnu")
        if title.startswith("Langage C -"):
            title = title.replace("Langage C -", "")

        try:
            chapter = Chapter.objects.get(title=title, channel=c)
        except Chapter.DoesNotExist:
            chapter = Chapter(creator=adminuser, contributor=adminuser, channel=c, title=title, slug=slugify(title))
            chapter.save()

        descr = "%s - %s" % (data.get("date", "Date inconnue"),
                             data.get("author", "Auteur inconnu"))
        activity = Activity(creator=adminuser, contributor=adminuser,
                            title=title,
                            chapter=chapter, description=descr)
        activity.save()

        url = data.get("url", "")
        if not url:
            # Default url
            url = "https://comin-ocw.org/contents/%s/camera.mp4" % dirname.split('/contents/')[-1]
        vid = Video(creator=adminuser, contributor=adminuser,
                    activity=activity,
                    title=title,
                    url=url)
        # Note: length is not initialized. We will get its duration
        # from the package just below.

        # Migrate license info
        licenses = [license
                    for license in ('cc-by', 'cc-by-nc', 'cc-by-sa', 'cc-by-nc-sa')
                    if data.get(license)]
        if licenses:
            # Associate license
            vid.license = License.objects.get(slug=licenses[0])
        pic = os.path.join(dirname, 'thumbnail.jpg')
        if not os.path.exists(pic):
            pic = os.path.join(dirname, 'imagecache', '00.png')
            if not os.path.exists(pic):
                pic = os.path.join(dirname, 'imagecache', '000.png')
        if os.path.exists(pic):
            with open(pic, 'rb') as f:
                vid.thumbnail.save(os.path.basename(pic), File(f))
            if not vid.activity.thumbnail:
                # Use same thumbnail
                with open(pic, 'rb') as f:
                    vid.activity.thumbnail.save(os.path.basename(pic), File(f))
                vid.activity.save()
            if not vid.activity.chapter.thumbnail:
                # Use same thumbnail
                with open(pic, 'rb') as f:
                    vid.activity.chapter.thumbnail.save(os.path.basename(pic), File(f))
                vid.activity.chapter.save()
            if not vid.activity.chapter.channel.thumbnail:
                # Use same thumbnail
                with open(pic, 'rb') as f:
                    vid.activity.chapter.channel.thumbnail.save(os.path.basename(pic), File(f))
                vid.activity.chapter.channel.save()
        vid.save()

        # Read data.json if available
        packageurl = data.get('dataurl', os.path.join(dirname, 'data.json'))
        if packageurl.startswith('http') or os.path.exists(packageurl):
            self.stdout.write("Loading data from %s" % packageurl)
            f = urllib.urlopen(packageurl.replace('https', 'http'))
            try:
                package = json.loads("".join(f.readlines()))
            except ValueError:
                package = {}
                f.close()
            if not package:
                print "************* Empty package: %s" % packageurl
                return
            # Update video duration
            vid.duration = package['medias'][0]['meta']['dc:duration'] / 1000.0
            slug = package['medias'][0]['id']
            if re.match('^\d', slug):
                # id starting with a number. Add a "m" (media) prefix.
                slug = "m" + slug
            if Video.objects.filter(slug=slug).exists():
                self.stdout.write("Duplicate video slug: " + slug)
                slug = slugify(title)
            else:
                vid.slug = slug
            vid.save()
            ats = {}
            for atjson in package['annotation-types']:
                sl = slugify(atjson['dc:title'])
                try:
                    at = AnnotationType.objects.get(slug=sl)
                except AnnotationType.DoesNotExist:
                    # Create the AnnotationType matching dc:title/slug
                    at = AnnotationType(creator=adminuser,
                                        created=convert_date(dateutil.parser.parse(atjson['dc:created'])),
                                        title=atjson['dc:title'],
                                        slug=sl,
                                        description=atjson['dc:description'])
                    at.save()
                ats[atjson['id']] = at

            if 'Notes' not in ats:
                at = AnnotationType.objects.get_or_create(title="Notes",
                                                          slug=slugify("Notes"),
                                                          defaults={
                                                              'creator': adminuser,
                                                              'description': "User note"
                                                          })[0]
                ats["Notes"] = at

            self.stdout.write("Copying %d annotations" % len(package['annotations']))
            for a in package['annotations']:
                if a['meta']['id-ref'] == "at_contributions":
                    at = ats['Notes']
                else:
                    at = ats[a['meta']['id-ref']]
                self.stdout.write(".", ending="")
                self.stdout.flush()
                tags = []
                creator = get_user(a['meta']['dc:creator'])
                contributor = get_user(a['meta']['dc:contributor'])
                title = a['content']['title']
                description = a['content']['description']
                group = get_group(a['meta']['id-ref'])
                visibility = VISIBILITY_PRIVATE
                if group is not None:
                    visibility = VISIBILITY_GROUP
                    # Use "Notes" type since we now have the group information
                    at = ats['Notes']
                if at.title not in ('Quiz', 'QuizPerso', TYPE_SLIDES, 'Partie'):
                    description = description or title
                    title = ""
                if at.title in ('Quiz', TYPE_SLIDES, 'Partie'):
                    visibility = VISIBILITY_PUBLIC
                    creator = contributor = get_user('coco')
                if 'public' in at.title.lower():
                    visibility = VISIBILITY_PUBLIC
                    at = ats['Notes']
                m = re.match("^\[([\w-]+,)?(\w+)](.*)", description)
                if m:
                    creator = contributor = get_user(m.group(2), context=a['meta']['id-ref'])
                    if m.group(1) is not None:
                        tags.append(m.group(1).strip(',').strip().lower())
                    description = m.group(3).strip()
                if group and not creator in group.user_set.all():
                    group.user_set.add(creator)
                an = Annotation(creator=creator,
                                contributor=contributor,
                                created=convert_date(dateutil.parser.parse(a['meta']['dc:created'])),
                                modified=convert_date(dateutil.parser.parse(a['meta']['dc:modified'])),
                                annotationtype=at,
                                video=vid,
                                begin=long(a['begin']) / 1000.0,
                                end=long(a['end']) / 1000.0,
                                title=title,
                                visibility=visibility,
                                group=group,
                                description=description)
                # FIXME: handle tags
                if 'data' in a['content']:
                    an.contenttype = a['content'].get('mimetype', 'application/json')
                    an.contentdata = json.dumps(a['content']['data'])
                elif 'level' in a['content']:
                    an.contenttype = 'application/json'
                    an.contentdata = json.dumps({'level': a['content']['level']})
                elif at.title == TYPE_SLIDES:
                    # Enforce level 1
                    an.contenttype = 'application/json'
                    an.contentdata = json.dumps({'level': 1})

                if 'img' in a['content']:
                    img = a['content']['img']['src']
                    if ('note.png' not in img and 'contribution.svg' not in img):
                        pic = os.path.join(dirname, a['content']['img']['src'])
                        if os.path.exists(pic):
                            with open(pic, 'rb') as f:
                                an.thumbnail.save(os.path.basename(pic), File(f))
                an.save()
                for t in tags:
                    an.tags.add(t.lower())