VikeLabs / lecshare

A React application with typescript implementation: Making lectures more accessible for students with auditory, visual, or learning impairments; and Improving learning outcomes for students in lecture-based courses.
https://vikelabs.github.io/lecshare/
GNU General Public License v3.0
5 stars 3 forks source link

Audio file conversion #65

Closed aomi closed 4 years ago

aomi commented 4 years ago

When a lecture audio recording is uploaded to our service, we need to encode this audio to another codec/bitrate etc.

When a file is uploaded, it is first put inside a bucket.

First step would be given an S3 object key, it will convert that file and put it in the same directory.

https://github.com/serverlesspub/ffmpeg-aws-lambda-layer https://intoli.com/blog/transcoding-on-aws-lambda/

Part 2

For the newly converted version of the audio, set the metadata. This could include setting the Content-Type to the proper one ie. audio/ogg etc. Maybe a key to reference the original file as well? We need the content type though or we will have problems later one.

Turning this into a Lambda

A Lambda can be invoked in many ways. We are probably interested in S3 bucket events (an event is fired when an object is placed inside a bucket etc.) or we will run a Lambda invoked from another Lambda.

An example of this would be our API Lambda that handles the file upload will fire a request for this newly uploaded file to process.

Long story short, given an JSON object (the arguments of the Lambda pretty much) , run the conversion with these specified parameters.

Make a struct and add json tags, use this to run the audio encode etc.

Some documentation on invoke. https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html Some Golang specific documention for such. https://docs.aws.amazon.com/sdk-for-go/api/service/lambda/#Lambda.Invoke

malcolmseyd commented 4 years ago

What's the preferred bitrate and audio format? I was thinking 128kbps Ogg-Vorbis.

aomi commented 4 years ago

That seems like a good balance! Maybe go mono too.

On Tue., Mar. 24, 2020, 5:00 p.m. Malcolm Seyd, notifications@github.com wrote:

What's the preferred bitrate and audio format? I was thinking 128kbps Ogg-Vorbis.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/VikeLabs/lecshare-api/issues/15#issuecomment-603565903, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANNEMAMDAT3YG2ZC2RIIL3RJFCQVANCNFSM4LP5GOYA .

malcolmseyd commented 4 years ago

Completed part 2 via this commit.

Content-Type is audio/ogg, x-amz-meta-uncompressed-file-key is the key to the original file.

aomi commented 4 years ago

At this point. We have to think about how we want to invoke this operation. A S3 event or do we want to invoke it manually.

https://github.com/aws/aws-lambda-go/tree/master/events

Note that there is not an example of an async invocation from within a lambda... Might require some investigative work by dumping what the event parameter holds.

Below is an example of how one might "lambdafy" some code. In this case, it's just an S3 event.

func lambdaHandler(ctx context.Context, event events.S3Event) {
    for _, record := range event.Records {
        s3 := record.S3
        fmt.Printf("[%s - %s] Bucket = %s, Key = %s \n", record.EventSource, record.EventTime, s3.Bucket.Name, s3.Object.Key)
    }
}
malcolmseyd commented 4 years ago

Alright, how's this? https://github.com/VikeLabs/lecshare-api/commit/2d6f2324536cce9fe8c2d280e3d81a740ec52a17

I went the automatic invocation route because it seems easiest. This way means that we have a preset bitrate for all conversions, unless we can have a "desired-bitrate" metadata on the original file or something of the sort.

aomi commented 4 years ago

I think the problem with the S3 bucket approach is passing in the parameters on how we want to execute this conversion. Also, it would get triggered each time a new object is added into the S3 bucket so if we want to use this we would probably define another bucket that is strictly used if we want to encode.

aomi commented 4 years ago

I'm overthinking it, let's just do this. Setup an S3 bucket as a temporary place to store these and setup a event trigger. This encoded file will be stored in the lecshare assets bucket.

aomi commented 4 years ago
func executeLocalLambdaHandler() {
    event := events.S3Event{
        Records: []events.S3EventRecord{
            events.S3EventRecord{
                S3: events.S3Entity{
                    Bucket: events.S3Bucket{
                        // add mock attributes here 
                    },
                    Object: events.S3Object{    
                        // add move attributes here
                    },
                },
            },
        },
    }
    ctx := context.Background()
    lambdaHandler(ctx, event)
}

func lambdaHandler(ctx context.Context, event events.S3Event) {

}

Example of how to execute / mock the S3 event.

aomi commented 4 years ago

iOS Safari does not support Vorbis (libopus) https://caniuse.com/#feat=ogg-vorbis

malcolmseyd commented 4 years ago

Okay, I think AAC is our best bet. It has pretty wide support and is close to OPUS in quality per bitrate.

aomi commented 4 years ago

I think encoding for both would be neat. We get into licensing problems with the ffmpeg lambda layer.

malcolmseyd commented 4 years ago

If the issues are with the audio encoders, we can use OPUS for most browsers and MP3 for iOS Safari, as both are free formats. As for LGPL compliance, I'm not sure how that works.

aomi commented 4 years ago

I think you can close this and any further features/fixes will be its own separate ticket.

malcolmseyd commented 4 years ago

Closing ticket, all features on the ticket have been implemented.

aomi commented 4 years ago

https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html Apparently it be that easy @malcolmseyd