Beginnings in Golang and AWS – Part I

Part I – Introduction, Go, and Prerequisites

The series of blogs describe my journey learning Golang so far, with particular reference to AWS services. In them, I’ll be covering how I was able to achieve a task with AWS services with Go, but also what I learnt about Go at the same time. In addition to some services already mentioned in previous blogs, we’ll also be covering Lex, API Gateway, Lambda, and Alexa Skills.


DSL’s aside, it’s been quite some time since I’ve endeavored to learn a new language in IT. Aside from a smattering of parsing through some Ruby and C# code on occasions and a bit of Python with BOTO3 for AWS stuff, it’d be fair to say the last one I learned to any level of depth was PowerShell.


Already providing support for Node.js, Java, C# and Python with Lambda, AWS announced in January this year the addition of Go (short and more commonly used form of Golang). I’ve seen a lot of enthusiasm around the communities about Go, and with it marked as cross platform, fast, and of a relatively simple nature (sorta), I decided I’d give this a bash (no pun intended).

Whether it’s because I’m over-enthusiastic or (more likely) of a completely disorganized mind, my usual modus operandi involves skipping “hello world” learning completely and just diving in. Most certainly not a purist compliant approach…
I figured a good way to try this would be to adapt some of the PowerShell scripts I’ve written previously that feature here. Unoriginal for sure, but as it’s fresh in my mind, why not try with Golang to perform the creation of an SRT file?

Previously discussed in the PowerShell blogs, the task effectively comprises uploading a media file to an S3 bucket, creating a Transcribe job, obtaining the results, and then converting them.

As we’ll see later in this series of blogs though, additional options are available for how we carry some of these tasks out, making further automation and input sources possible.

For now though, we’ll get the pre-requisites out of the way.


  • An existing AWS account. You can sign up for a Free Tier account here
  • Credentials and configuration are setup. See here for information on how to do this.
  • Go is installed (see below)
  • AWS SDK for Go is installed (see below)
  • You have cloned the repo for the project from either its source or your own fork
  • You’ve a ready-to-hand MP4 media file
  • You have a suitable development environment, such as VS Code

Install Go

Naturally, you are going to need Go installed. You can find your appropriate binary at the downloads page of I’ll leave it to you to follow the specific installation instructions and any steps needed to fulfill requirements.

Install the AWS SDK for Go

You’ll also need the AWS SDK. Go has a really nice way to add packages to your environment, which is simply achieved by using the go get xxxxx, where xxxxx is the location of the package from the command line. Go handles the rest.

For installation of the AWS SDK for Go, simply use the following:

go get

Install VS Code (optional)

I currently use VS Code, which has some nice extensions to do tasks such as formatting, and automatic adding and removal of import commands. If you’re not currently using a development environment, or just simply fancy trying it out, you can obtain the binaries (available for Windows, OSX, and Linux) from here:

Add the Go Extention to VS Code

Follow the instructions and after installation is complete, launch VS Code. Add the extention ms-vscode.go, which provides features such as mentioned above within the development environment.


With the prerequisites now in place for us to use Go with AWS services, we can begin the process of putting together code which will help us achieve the tasks we’ve already mentioned.

In the next blog, we’ll dive into writing a script that will upload our media file to S3 using the SDK, and at the same time learning about a bit about Go.

Thanks for reading!


When Marvin Gaye Met Amazon Transcribe & PowerShell – Automating Subtitle Creation – Part III

“I Heard it Through the Grape Vernon”

Part two of this series saw us put the code in place to allow us to upload the media file, create the transcription job, and download the results. With this complete, it’s time to move on to the next, and final, stage. That is, processing the JSON file, and creating an SRT file from it.

NB. You can find the code used in this blog, and additional documentation, at my Github project, aws-powershell-transcribe2srt:

Initially, we’ll read the contents of the json file into a variable and specifically use the items section, which contains the word-by-word breakdown. At the same time, some other variables are set with defaults.

$Transcription = Get-Content -Path "pathtomyjsonfile"
$Transcription = $Transcription | ConvertFrom-Json
$Transcription = $Transcription[0].results.items

#Set initial variables
$index = 0
$sequenceno = 0
$srtinfo = ""
$subtitle = ""

Next, the Transcription variable needs to be processed. There’s several things that need to be taken into account:

  • The obvious one is that we need to parse through each item in the object, requiring a loop.
  • We also want to ensure that the number of words displayed per line does not exceed recommendations
  • In relation to the above, we also need to define the end time for each sequence the same as the last word.
  • Lastly, punctuation needs to be taken into account.

Outer Loop – Beginning

Using a while loop, the variable $strlen is set to zero. This variable will contain a count of the number of characters in the current sequence being processed.

Process the Start Time Attribute

Then, the time at which the word was said, start_time is read. In its original json format, this is as below.

However, the format for an SRT file of a time element consists of the number of hours, minutes, seconds, and milliseconds. All but the last of these use a fixed two character zero-padded digit format. The last uses three digits.

00:02:30.268 --> 00:02:41.958

We’ll convert this string into the required style by first converting it to a timespan object, and then using string formatting to set it as required. Variables are also set for the subtitle text, the sequence number, and a flag to indicate that we are beginning the first line of this subtitle sequence. A variable is set for the end time too, and the process continues until 64 characters have been exceeded.

#Repeat this process until we have reached the end of the results
While ($index -lt $transcription.count) {
$strlen = 0
#Grab the start time of the item we are reading and covert it SRT time format
$sttime = $transcription[$index].start_time
$sttime = [timespan]::FromSeconds($sttime)
$starttime = "{0:hh}:{0:mm}:{0:ss},{0:fff}" -f $sttime
$subtitle = ""
$sequenceno += 1
$firstrow = $true

Inner Loop

An inner loop is also required, since we want the subtitles to be refreshed after two lines and with a maximum of 64 characters. Whether the item is a pronunciation (aka word) or punctuation needs to be taken into account, as well as setting the end time marker for the sequence when two lines have been occupied.

The type of item is read (pronunciation or punctuation), its content, and the length of the string tally is increased in line with this. Based on the type of item, the subtitle string is appended accordingly. When the length of the string exceeds 32 characters, and we are still on the first row, a new line character is added, and the variable indicator set to indicate that the subsequent content will be on the second line.

#Repeat this until we have either reached the last item in results
#or the length of the lines we are reading is greater than 64 characters
While (($strlen -le 64) -and ($index -le $transcription.count)) {
$type = $transcription[$index].type
$text = $transcription[$index].alternatives.content
$strlen += $text.length

Switch ($type) {
    "pronunciation" {$subtitle += "$text "}
    "punctuation" {
        If ($subtitle.Length -gt 0) {
            $subtitle = $subtitle.substring(0, $subtitle.length - 1) + $text
        Else {
            $subtitle += $text
#If the length of the current string is greater than 32 and this
#is the first line of the sequence, then add a return character to it
If (($strlen -gt 32) -and ($firstrow)) {
    $subtitle += "`n"
    $firstrow = $false

#If the last character is a '.', then we need to set
#the end time attribute to the previous indexes one
#since punctuation characters to not have a time stamp
If ($type -eq "punctuation") {
    $entime = $transcription[$index - 1].end_time
Else {
    $entime = $transcription[$index].end_time
$entime = [timespan]::FromSeconds($entime)
$endtime = "{0:hh}:{0:mm}:{0:ss},{0:fff}" -f $entime  
$index += 1

Outer Loop – End

When the inner loop is complete, it signifies a new sequence is ready. This part simply creates the appropriate representation of the sequence as a string, and appends it to the variable holding the entire contents of what will become the SRT file.

            #Setup the string that is refers to these two
            #lines in SRT format
            $subdetail = "
$starttime --> $endtime

            #Append this to the existing string
            $srtinfo += $subdetail

Writing the SRT File

Lastly, the contents of the $srtinfo variable are written to file.

        #Now output the results to our .srt file
        $srtinfo | Set-Content $DestinationPath -Force

Viewing the Results

At this point, it really depends on what you want to do with the SRT file and accompanying media one. Media players like VLC allow you to manually add an SRT file to a playing video, and most current televisions with USB will be happy to display the subtitles provided the filenames (without extension) match.
If you really want to go full (non-pron) hardcore, you could add the SRT info as a stream directly into the media file, using a tool like FFMPEG, which allows you to multiplex, or even to “burn” the subtitles onto the video. Using this method, vloggers really wanting to reach their audience could make multiple language subtitles available in this video file.


The combination of AWS services S3 and Transcribe, coupled with PowerShell and their AWS module for it, make it a relatively straightforward process to obtain a transcription of a media file which can be converted to SRT format for later use.

Also, as a final word, bear in mind that as a service meant for transcribing relatively silent environments with spoken (not sung) words, sometimes the results of a media file can be a little bit…misunderstood. Often with humerous results… 🙂

Marvin’s on his own

Let’s help him with some words

Thats Marvin SRTd

Wrong words but’s let’s karaoke anyway

Thanks for reading, and feedback always welcome.

Coming soon…a slight departure from the norm with an advanced version of this but using Golang.

Think i need to see about getting me another domain name…


When Marvin Gaye Met Amazon Transcribe & PowerShell – Automating Subtitle Creation – Part II

“I Heard it Through the Grape Van”

With the background set in the previous post for what we’ll be aiming to achieve, it’s time to move forward with getting things into gear.
Todays post covers how to upload the media file to s3, create the Transcribe job to process it, and finally download the results locally.

Quick Recap

This projects demonstrates the use of the AWS Transcribe service and PowerShell to create an SRT (subtitle) file from a media file.

Our project makes use of:

  • PowerShell Core
  • AWS PowerShell Core Cmdlets
  • AWS S3
  • AWS Transcribe Service
  • An MP4 video file


Before going into the nitty gritty, you need to ensure all of the following are in place:

  • An existing AWS account. You can sign up for a Free Tier account here
  • Credentials and configuration are setup. See here for information on how to do this.
  • PowerShell Core is installed (available cross platform here)
  • The AWS PowerShell Net Core module is installed.
  • You’ve a ready-to-hand MP4 media file
  • You have cloned the repo for the project from either its source or your own fork

Sequence of Events to Transcribe the File

The order of events that need to happen is relatively straightforward:

  • Upload the file to S3
  • Create a Transcribe job
  • Wait for job to finish
  • Download the JSON file

Upload the file to S3

We’ll start out defining some variables and defaults to make things a bit easier, then the Write-S3Object cmdlet takes care of itself:

$AWSDefaultParameters = @{
    profilename = 'development'
    region      = 'eu-west-1' 

#Set parameters as required
$Bucket = 'tim-training-thing'
$Path = "~/Desktop/videoplayback.mp4" 

#Let's get the file item so we can use some of its properties

$fileitem = Get-Item -Path $Path

#Set the S3 uri prefix and uri for the S3 object's key
$prefix = ''
$s3uri = "$prefix/$Bucket/$($" 

#Upload it to S3
Write-S3Object -BucketName $Bucket -File $Path @AWSDefaultParameters

Create a Transcribe job

All Transcribe jobs have an associated job name associated with this. For this script, I’ve used the GUID class to create a unique one. We define this and the name of the results file that will be used when it’s downloaded from a completed job. Then the Start-TRSTranscriptionJob cmdlet is used to initiate the task. The $s3uri variable is used to tell Transcribe where to get the file it is to process.

#Define a unique guid to be used as the job name and the output results file.
$jobname = [Guid]::NewGuid() | Select-Object -ExpandProperty Guid
$resultsfile = './result.json'
$null = Start-TRSTranscriptionJob -Media_MediaFileUri $s3uri -TranscriptionJobName $jobname -MediaFormat mp4 -LanguageCode en-US @AWSDefaultParameters

Wait for job to finish

A basic loop is put in place which checks the status of the Transcribe job every five seconds. The loops continues until the job status changes from IN_PROGRESS, indicating either a failure or completion of it.

#Job processing will run async, so it's up to you how you deal with this.
        #For this one we'll take ten second naps in between checks of the status
        $results = Get-TRSTranscriptionJob -TranscriptionJobName $jobname @AWSDefaultParameters 

        While ($results.TranscriptionJobStatus -eq 'IN_PROGRESS') {
            Start-Sleep -Seconds 5
            $results = Get-TRSTranscriptionJob -TranscriptionJobName $jobname @AWSDefaultParameters 

Download the JSON file

When a job has successfully executed, visible by its COMPLETED status, it stores the result in an s3 bucket of its own choice. The location is not in your own personal bucket, and has an expiry life. By querying the TranscriptFileUri property of the job status, we can get the location where it is stored. You’ve then got the choice of using the S3 Manager cmdlet for downloading the file, or alternatively (in this case), simply with Invoke-Webrequest.

 If ($results.TranscriptionJobStatus -eq 'COMPLETED') {
            $transcripturi = $results.Transcript.TranscriptFileUri 
            Invoke-Webrequest -Uri $transcripturi -OutFile $resultsfile

Part III will cover the largest part of the process, converting the job results into the SRT file we’ll use with the original video.
Thanks for reading!