Skip to content

A Python Flask API for an audio metadata file server which uses a MongoDB NoSQL database backend

License

Notifications You must be signed in to change notification settings

manishmeganathan/metaudio

Repository files navigation

AudioServer

A Flask-RESTful Application Server that serves audio file metadata from a MongoDB server.

Actions Workflow License

Version: 1.0.0
Platform: Google Cloud Platform - Cloud Run
Language: Python 3.7 and 3.8

Introduction

This repository is a Flask Application that simulates an audio file server while using a MongoDB NoSQL database. The application is hosted on Google Cloud Platform as container that runs on the Cloud Run platform.

Application URL - https://audioserver-3wow3hatda-de.a.run.app
please contact the repository owner if the above URL is not functional

AudioFiles package

This package contains the classes Song, Podcast and Audiobook all of which derive from the Audio class. It also contains a couple of custom exception MetadataValueError and MetadataGenerationError.

The classes are all implemented as dataclasses, which was introduced in Python 3.7. This was because the classes are only storing metadata values and do not have any other function, which is exactly the intended use-case for dataclasses.

The full documentation for the package is available in the docs directory

Dependencies

  • PyMongo and dnspython for MongoDB.
  • Flask, Flask-RESTful and gUnicorn for the web framework and server runtime.
  • pyTest for the test suites.

Database Document Formats

The audio files are stored in the database in the formats discussed below.

  • The 'uploadtime' is generated by the respective class when the object is created for the first time. If 'uploadtime' is already in the metadata, it is parsed (when reading from the database). The 'uploadtime' is stored as an ISO8601 formatted string.
  • The '_id' is generated by the respective class when the object is created by hashing the 'name', 'duration' and 'uploadtime'. If it is already in the metadata, it is used instead of generating.

Song

The object only requires the 'name' and 'duration' fields in the metadata dictionary.

{
    "_id": <int>,
    "type": "Song",
    "name": <str> (100 chars),
    "duration": <int> (positive),
    "uploadtime": <str> (ISO8601)
}

Podcast

The object only requires the 'name', 'host' and 'duration' fields in the metadata dictionary. The 'participants' field is optional and is stored as an empty list if not provided.

{
    "_id": <int>,
    "type": "Podcast",
    "name": <str> (100 chars),
    "host": <str> (100 chars),
    "participants": <list> (opt, 10 str members of 100 chars each max),
    "duration": <int> (positive),
    "uploadtime": <str> (ISO8601)
}

Audiobook

The object only requires the 'name', 'author', 'narrator' and 'duration' fields in the metadata.

{
    "_id": <int>,
    "type": "Audiobook",
    "name": <str> (100 chars),
    "author": <str> (100 chars),
    "narrator": <str> (100 chars),
    "duration": <int> (positive),
    "uploadtime": <str> (ISO8601)
}

AudioServer API

The AudioServer application has 4 API endpoints which are discussed below

Create

This functionality is available at the /create endpoint of the application URL.

  • Accepts only POST requests.
  • Request JSON must follow the following format
    {
        "audioFileType": <str>,
        "audioFileMetadata": <dict>
    }
    
  • The audioFileType key must be one of "Song", "Podcast" and "Audiobook". Case Insensitive.
  • The AudioFileMetadata key must contain the appropriate fields for the specified types in the correct formats.
  • The Response JSON has the following format
    {
        "status": 200,
        "message": "Create Complete",
        "result": f"{audioFileType} file with ID {DocumentID} has been created",
        "document": {DocumentID} (int)
    }
    

Delete

This functionality is available at the /delete endpoint of the application URL.

  • Accepts only GET requests.
  • The route must be in the format - delete/<audioFileType>/<audioFileID>
  • The audioFileType key must be one of "Song", "Podcast" and "Audiobook". Case Insensitive.
  • The audioFileID key must be an integer that corresponds to the file to delete. If no file is found for the given type, then no document is deleted.
  • If no document was deleted the response JSON has the following format
    {
        "status": 200,
        "message": "Delete Complete",
        "result": f"No document deleted"
    }
    
  • If a document is deleted, the response JSON has the following format
    {
        "status": 200,
        "message": "Delete Complete",
        "result": f"{audioFileType} file with ID {DocumentID} has been deleted",
        "document": {DocumentID} (int)
    }
    

Update

This functionality is available at the /update endpoint of the application URL.

  • Accepts only POST requests.
  • The route must be in the format - update/<audioFileType>/<audioFileID>
  • Request JSON must follow the following format
    {
        "audioFileType": <str>,
        "audioFileMetadata": <dict>
    }
    
  • The audioFileType key must be one of "Song", "Podcast" and "Audiobook". Case Insensitive. It must match the audioFileType provided in the URL route.
  • The AudioFileMetadata key must contain the appropriate fields for the specified types in the correct formats.
  • The audioFileID key must be an integer that corresponds to the file to delete. If no file is found for the given type, then a 400 error is returned and no document is updated.
  • The Response JSON has the following format
    {
        "status": 200,
        "message": "Update Complete",
        "result": f"{audioFileType} file with ID {DocumentID} has been updated",
        "pre-update": <dict>,
        "post-update": <dict>,
        "document": {DocumentID} (int)
    }
    

Get

This functionality is available at the /get endpoint of the application URL.

  • Accepts only GET requests.
  • The route must be in on of the following format
    • get/<audioFileType>
    • get/<audioFileType>/<audioFileID>
  • The audioFileType key must be one of "Song", "Podcast" and "Audiobook". Case Insensitive.
  • The audioFileID key must be an integer that corresponds to the file to delete. If no file is found for the given type, then no document is returned.
  • If only the audioFileType is in the route (format 1), all files of the given type will be returned.
  • The Response JSON has the following format
    {
        "status": 200,
        "message": "Get Complete",
        "result": f"{ResultCount} result(s) found",
        "documents": <list> (list of dict),
        "matches": ResultCount (int)
    }
    

Errors

  • If an invalid request is received, the server returns a 400 response with the following format
    {
        "status": 400,
        "message": "Bad Request",
        "error": <str>
    }
    
  • If the server has any other error, it returns a 500 response with the following format
    {
        "status": 500,
        "message": "Internal Server Error",
        "error": <str>
    }