Sometimes when you embark on a new piece of research, serendipity strikes which just makes the job so much simpler than you’d imagined it to be.
In this case, there are already a series of GitHub examples for integrating Azure Media Services and Azure Blob Storage via Azure Functions. It’s heartening to know that my use case is a commonly enough occurring one to have example code already up for pilfering.
If we recall the application ‘design’ referenced in previous blogs, the ‘WatchFolder’ console application performs a very specific function – watching a blob storage container, and when it sees a new file of a specific naming convention appear (guid.mp4), it kicks off the Transcription application. The Transcription application moves the file into Azure Media Services, performs subtitle transcription, copies out the subtitles file, runs an FFMPEG job locally to combine the video and the subtitles, and then finally tweets out the resultant subtitled video.
Through exploration of the GitHub examples linked above, specifically the ‘100-basic-encoding’ example, I can actually completely get rid of the WatchFolder application, and move everything in Transcription up the FFMPEG job into a function.
This is by virtue of the fact that there are pre-defined templates from which functions can be built, and one of those is a C# Function which will run whenever a blob is added to a specified container. Hurrah! Literally just by choosing this Functions template, I have removed the need for a whole C# console app which ran within a VM – this is already valuable stuff.
Ok! So to get cracking with building out on top of the example function that looks to fit my use case, as ever we just hit the ‘Deploy to Azure’ button in the Readme.md, and start to follow the instructions.
Actually, before we continue, the best thing to do is to fork this project into my own GitHub repo to protect against code-breaking changes to the example repo. Just use the Fork button at the top of the GitHub page, and choose the where you want to fork it to. You’ll need to be signed into a GitHub account.
Now successfully forked, we can get on with deployment.
Enter some basic information – resource group, location, project you want to deploy etc. In this case, we’re taking the 100-basic-encoding function. Easy peasy!
Aaaaaand Internal Service Error. Well, if everything went smoothly, we’d never learn anything, so time to get the ‘ole troubleshooting hat on.
The problem here is a common one if you use a lot of accounts for testing in Azure. When we look at the GitHub sourcecontrols provider at https://resources.azure.com. This particular test account has never deployed from GitHub before, and so auth token is not appropriately set.
This is easily fixed in the Azure Portal. Open up your Functions App, select Function App Settings and then Configure Continuous Integration:
And then run through Setup to create a link to GitHub. This will kick off an OAuth process through to your GitHub account, so just follow the prompts.
After completing this and refreshing https://resources.azure.com/providers/Microsoft.Web/sourcecontrols/GitHub, the token now shows as set.
Excellent! Let’s redeploy 🙂
For no other reason than to show the consistency of approach between a traditional C# console application and a C# Azure Function, below I have pasted the bulk of the TranscribeVideo console app down to just above the FFMPEG kick-off directly alongside the out of the box Function example code with zero changes yet. It’s also rather gratifying to see that my approach over a year ago, and that taken in this Function have significant parallels 🙂
Of course the example code is designed to re-encode an MP4 and output it into an output blob, whereas what we want is to run an Indexing job and then output the resultant VTT subtitles file into an output blob. This only takes a handful of tiny changes, made all the more easy by referencing my existing code.
With all the required tweaks to the example code – and they are just tweaks, no major changes – I have decommissioned a full console application, and migrated almost 80% of a second console application into a Functions app. This has exceeded my expectations so far.
Just for the avoidance of doubt, it all works beautifully. Below is a screenshot of the output log of the Function – it started automatically when I added a video file to the input container.
Above you can see the Function finding the video file Index.mp4, submitting it to Azure Media Services, running the transcription job, then taking the .vtt subtitles file and dropping it into the output container.
Here it is in Azure Storage Explorer:
So with that complete, I now need to look at how I encode the subtitles into the video and then tweet it. When I first wrote this many moons ago, it was significantly easier (or maybe actually only possible) to do this in an IaaS VM using FFMPEG to encode the subtitles into the video file. It looks like this might be a simple built-in function in Azure Media Services now. If that’s the case and it’s cost-effective enough, then I may be able to completely decommission the need for any IaaS, and migrate the entire application-set through into Functions.
I also want to change the function above to take advantage of the beta version of the Azure Media Indexer 2, as it suggests it should be able to do the transcription process significantly faster. If you look at the log file above, you’ll see that it took around 3 minutes to transcribe a 20 second video. If this can be sped up, so much the better.
So a few next steps to do, stay tuned for part 4 I guess! 🙂