Beispiel #1
0
def videoCreationBatch():
    from auth import get_user, is_superuser
    if not is_superuser():
        return action_401()
    if request.method=="GET":
        chdir(config.INGEST_DIRECTORY)
        files=[f for f in listdir(getcwd()) if f[0] != '.']
        return json.dumps(files)
    else:
        packet=request.json

        ids = [up.get('id') for up in packet]

        if len(set(ids)) is not len(ids):
            return bundle_400("Duplicate IDs found. Cannot update." % s)

        # test everything before we start ingesting, otherwise half the batch
        # might get completed before we get an error. easier to just reject everything
        # than half of everything
        for up in packet:
            i = up['id']
            dupe = assets.find_one({'@graph.ma:locator': {'$elemMatch': {'@id': i}}})
            mp4 = (unicode(config.MEDIA_DIRECTORY) + i + '.mp4').encode('utf-8')
            webm = (unicode(config.MEDIA_DIRECTORY) + i + '.webm').encode('utf-8')
            if path.isfile(mp4) or path.isfile(webm) or dupe is not None:
                return bundle_400("That file (%s) already exists; try another unique ID." %i)

        for up in packet:
            result = MediaAsset.set_new_file(up['pid'], up['id'], up['filepath'])
            if not result[0]:
                return bundle_400(result[1])

	return "Success"
Beispiel #2
0
def audioCreationBatch():
    import mutagen
    import uuid
    import os
    from werkzeug.utils import secure_filename
    from auth import is_superuser

    if not is_superuser():
        return action_401()

    files = request.files.getlist('audio[]')

    if not len(files):
        return bundle_400("Missing form field 'audio[]'")

    incompatible = filter(lambda x: not x.filename.endswith('mp3'), files)

    if len(incompatible):
        return bundle_400("Only MP3 files are supported.")

    results = []
    for f in files:
        ext = f.filename.split('.')[-1]
        filename = secure_filename(f.filename.split('.', 1)[0]) \
                   + str(uuid.uuid4()) + '.' + ext

        path = os.path.join(config.MEDIA_DIRECTORY, filename)
        f.save(path)

        id3 = mutagen.File(path, easy=True)  # metadata
        _id = str(ObjectId())

        audio = assets.Video()
        audio['_id'] = _id
        audio['@graph']['dc:type'] = 'hummedia:type/humaudio'
        audio['@graph']['pid'] = _id
        audio['@graph']['ma:title'] = id3.get('title', [f.filename])[0]
        audio['@graph']['ma:hasContributor'] = [{
            '@id': '',
            'name': x
        } for x in id3.get('artist', [])]

        try:
            audio['@graph']["ma:date"] = int(id3.get('date')[0])
        except:
            audio['@graph'][
                'ma:date'] = 1970  # TODO: this requires a number, but I don't have one for it

        audio['@graph']["ma:locator"] = [{
            "@id":
            '.'.join(filename.split('.')[0:-1]),
            "ma:hasFormat":
            "audio/" + ext,
            "ma:hasCompression": {}
        }]
        audio.save()
        audio['@graph']['ma:locator'][0]['@id'] += '.mp3'
        results.append(audio['@graph'])

    return mongo_jsonify(results)
Beispiel #3
0
    def post(self, id=None):
        # Verify that a user is logged in.
        from auth import get_profile
        userid = get_profile()['userid']
        if not userid:
            return action_401()

        data = self.request.get_json()

        # Require clips to have a start time.
        # End time is optional.
        if 'start' not in data:
            return bundle_400('clips must have a start time!')

        # Validate media id.
        if 'mediaid' in data:
            query = {'_id': data['mediaid']}
            if not assets.find_one(query):
                return bundle_400('invalid media id!')
        else:
            return bundle_400('clips must have a valid media id!')

        # Populate the new object with all our data.
        self.bundle = self.model()
        self.set_attrs()
        self.bundle['userid'] = userid
        self.bundle['_id'] = str(ObjectId())

        return self.save_bundle()
Beispiel #4
0
def audioCreationBatch():
    import mutagen
    import uuid
    import os
    from werkzeug.utils import secure_filename
    from auth import is_superuser

    if not is_superuser():
      return action_401()

    files = request.files.getlist('audio[]')
    
    if not len(files):
      return bundle_400("Missing form field 'audio[]'")

    incompatible = filter(lambda x: not x.filename.endswith('mp3'), files)
    
    if len(incompatible):
      return bundle_400("Only MP3 files are supported.")

    results = []
    for f in files:
        ext = f.filename.split('.')[-1]
        filename = secure_filename(f.filename.split('.', 1)[0]) \
                   + str(uuid.uuid4()) + '.' + ext

        path = os.path.join(config.MEDIA_DIRECTORY, filename)
        f.save(path)

        id3 = mutagen.File(path, easy=True) # metadata
        _id = str(ObjectId())

        audio = assets.Video()
        audio['_id'] = _id
        audio['@graph']['dc:type'] = 'hummedia:type/humaudio'
        audio['@graph']['pid'] = _id
        audio['@graph']['ma:title'] = id3.get('title',[f.filename])[0]
        audio['@graph']['ma:hasContributor'] = [{'@id': '', 'name': x} for x in id3.get('artist',[])]

        try:
            audio['@graph']["ma:date"] = int(id3.get('date')[0])
        except:
            audio['@graph']['ma:date'] = 1970 # TODO: this requires a number, but I don't have one for it

        audio['@graph']["ma:locator"] = [
             {
                 "@id": '.'.join(filename.split('.')[0:-1]),
                 "ma:hasFormat": "audio/" + ext,
                 "ma:hasCompression": {}
             }
        ]
        audio.save()
        audio['@graph']['ma:locator'][0]['@id'] += '.mp3'
        results.append(audio['@graph'])

    return mongo_jsonify(results)
Beispiel #5
0
    def client_process(self,bundle=None,list=False,client=None):
        if not bundle:
            bundle=self.bundle
        if not client:
            client = self.request.args.get("client")

        c=clients.lookup[client]()
        m=assets.find_one(bundle["@graph"]["dc:relation"])
        m["@graph"]["resource"]=uri_pattern(m["@graph"]["pid"],config.APIHOST+"/video")
        m["@graph"]["type"]=resolve_type(m["@graph"]["dc:type"])
        m["@graph"]["url"]=[]
        for url in m["@graph"]["ma:locator"]:
            if m["@graph"]["type"]=="humvideo":
                host=config.HOST+"/video"
                ext="."+url["ma:hasFormat"].replace("video/","")
            elif m["@graph"]["type"]=="humaudio":
                host=config.HOST+"/video"
                ext="."+url["ma:hasFormat"].replace("audio/","")
            elif m["@graph"]["type"]=="yt":
                host="http://youtu.be"
                ext=""
            m["@graph"]["url"].append(uri_pattern(url["@id"]+ext,host))
        resp_context=True if not list else False
        try:
            required = True if bundle["@graph"]["pid"] in m["@graph"].get("ma:hasPolicy") else False
        except TypeError:
            return bundle_400("That annotation list isn't currently associated with any media.")
        return c.serialize(bundle["@graph"],m["@graph"],resp_context,required)
Beispiel #6
0
def videoCreationBatch():
    from auth import get_user, is_superuser
    if not is_superuser():
        return action_401()
    if request.method=="GET":
        chdir(config.INGEST_DIRECTORY)
        files=[f for f in listdir(getcwd()) if f[0] != '.']
        return json.dumps(files)
    else:
        from PIL import Image
        from shutil import move
        from helpers import getVideoInfo
        packet=request.json
        for up in packet:
            filepath=unicode(config.INGEST_DIRECTORY + up['filepath'])
	    new_file=unicode(config.MEDIA_DIRECTORY + up['id'] + ".mp4")
	    if path.isfile(new_file):
		return bundle_400("That file already exists; try another unique ID.")
            if path.isfile(filepath.encode('utf-8')):
                md=getVideoInfo(filepath.encode('utf-8'))
                poster = config.POSTERS_DIRECTORY + "%s.jpg" % (up["id"])
                thumb = config.POSTERS_DIRECTORY + "%s_thumb.jpg" % (up["id"])
                move(filepath.encode('utf-8'), new_file.encode('utf-8'))
                assets.update({"_id":up["pid"]},{"$set":{
                    "@graph.ma:frameRate":float(md["framerate"]),
                    "@graph.ma:averageBitRate":int(float(md["bitrate"])),
                    "@graph.ma:frameWidth":int(md["width"]),
                    "@graph.ma:frameHeight":int(md["height"]),
                    "@graph.ma:duration":int( round(float(md["duration"])) )/60,
                    "@graph.ma:locator": [
                        {
                            "@id": up["id"],
                            "ma:hasFormat": "video/mp4",
                            "ma:hasCompression": {"@id":"http://www.freebase.com/view/en/h_264_mpeg_4_avc","name": "avc.42E01E"}
                        },
                        {
                            "@id": up["id"],
                            "ma:hasFormat": "video/webm",
                            "ma:hasCompression": {"@id":"http://www.freebase.com/m/0c02yk5","name":"vp8.0"}
                        }
                    ]
                }})
                imgcmd = "avconv -i '%s' -q:v 1 -r 1 -t 00:00:01 -ss 00:00:30 -f image2 '%s'" % (new_file,poster)
                system(imgcmd.encode('utf-8'))
                chmod(poster,0775)
                im=Image.open(poster)
                im.thumbnail((160,90))
                im.save(thumb)
                chmod(thumb,0775)
                
                if not app.config.get('TESTING'):
                    from gearman import GearmanClient
                    client = GearmanClient(config.GEARMAN_SERVERS)
                    client.submit_job("generate_webm", str(up["id"]))
                else:
                    from ingest import generate_webm
                    result = generate_webm(file_id=up['id'])
                    if result == "ERROR":
                      raise Exception("Could not convert media file.")
	return "Success"
Beispiel #7
0
 def get(self,id,limit=0):
     q=self.set_query()
     if id:
         try:
             q['_id']=ObjectId(str(id))
         except Exception as e:
             return bundle_400("The ID you submitted is malformed.")
         if "enrollments" in self.request.args:
             info = self.get_bundle(q)
             en = self.get_enrollments(info['username'], info['userid'])
             en.update({"username": info['username'], '_id': q['_id']})
             self.bundle = en
         else:
             self.bundle=self.get_bundle(q)
         if self.bundle:
             self.bundle=self.auth_filter(self.bundle)
             if not self.bundle:
                 return action_401()
             self.set_resource()
             return self.serialize_bundle(self.bundle)
         else:
             return bundle_404()
     else:
         self.bundle=self.collection.find(q).limit(limit)
         return self.get_list()
Beispiel #8
0
 def post(self,pid=None):
     if self.acl_write_check():
         self.bundle=self.model()
         if not pid:
             if "username" in self.request.json:
                 self.bundle["_id"]=str(self.request.json.username)
             else:
                 return bundle_400()
         else:
             self.bundle["_id"]=str(ObjectId(pid))
         self.preprocess_bundle()
         setattrs=self.set_attrs()
         if setattrs.get("resp")==200:
             return self.save_bundle()
         else:
             return bundle_400(setattrs.get("msg"))
     else:
         return action_401()
Beispiel #9
0
    def patch(self, id):
        from auth import get_profile
        atts = get_profile()

        if self.request.json is None or 'replacement_file' not in self.request.json:
            return super(MediaAsset, self).patch(id)

        if not atts['superuser']:
            return action_401()

        found = assets.find_one({'_id': id})

        if not found:
            return bundle_404()

        file_id = None
        to_delete = []

        # find existing filenames
        for f in found['@graph']['ma:locator']:
            if file_id is not None and f['@id'] != file_id:
                raise Exception(
                    "Cannot replace file; multiple files with different IDs")

            file_id = f['@id']
            extension = f['ma:hasFormat'].split('/')[-1]
            fpath = config.MEDIA_DIRECTORY + f['@id'] + '.' + extension
            to_delete.append(fpath)

        from os import remove
        for f in to_delete:
            try:
                remove(f)
            except OSError:
                pass

        assets.update({'_id': id}, {'$set': {'@graph.ma:locator': []}})

        result = self.set_new_file(id, file_id,
                                   self.request.json['replacement_file'])
        if not result[0]:
            return bundle_400(result[1])

        return self.serialize_bundle(assets.find_one({'_id': id}))
Beispiel #10
0
 def get(self,id,limit=0):
     q=self.set_query()
     if id:
         try:
             q['_id']=ObjectId(str(id))
         except Exception as e:
             return bundle_400("The ID you submitted is malformed.")
         self.bundle=self.get_bundle(q)
         if self.bundle:
             self.bundle=self.auth_filter(self.bundle)
             if not self.bundle:
                 return action_401()
             self.set_resource()
             return self.serialize_bundle(self.bundle)
         else:
             return bundle_404()
     else:
         self.bundle=self.collection.find(q).limit(limit)
         return self.get_list()
    def patch(self, id):
        from auth import get_profile
        atts=get_profile()

        if self.request.json is None or 'replacement_file' not in self.request.json:
            return super(MediaAsset, self).patch(id)

        if not atts['superuser']:
            return action_401()

        found = assets.find_one({'_id': id})

        if not found:
            return bundle_404()

        file_id = None
        to_delete = []

        # find existing filenames
        for f in found['@graph']['ma:locator']:
            if file_id is not None and f['@id'] != file_id:
                raise Exception("Cannot replace file; multiple files with different IDs")

            file_id = f['@id']
            extension = f['ma:hasFormat'].split('/')[-1]
            fpath = config.MEDIA_DIRECTORY + f['@id'] + '.' + extension
            to_delete.append(fpath)

        from os import remove
        for f in to_delete:
            try:
              remove(f)
            except OSError:
              pass

        assets.update({'_id': id}, {'$set': {'@graph.ma:locator': []}})

        result = self.set_new_file(id, file_id, self.request.json['replacement_file'])
        if not result[0]:
            return bundle_400(result[1])

        return self.serialize_bundle(assets.find_one({'_id': id}))
Beispiel #12
0
    def update_lastview(self, id, limit=0):
        '''Update the last view time if the 'view' url parameter is used.'''
        self.bundle = self.model.find_one({'$or': [{'_id': str(id)}, {'_id': ObjectId(id)}]})
        if self.bundle:
            self.bundle = self.auth_filter(self.bundle)
            if not self.bundle:
                return action_401()
            self.bundle[u'@graph'][u'dc:lastviewed'] = datetime.utcnow()
            self.set_attrs()

            # Sometimes in the development testing database the ma:duration filed is missing.
            # This causes an error when the lastview field is updated.
            # This eats the error, which is probably not a best practice but makes the user
            # experience better.
            from mongokit.schema_document import RequireFieldError
            try:
                self.bundle.save()
            except RequireFieldError:
	        return mongo_jsonify({"resp":200})
	    return mongo_jsonify({"resp":200})
        else:
            return bundle_400('The ID you submitted is malformed.')