Making an app to do audio transcription

Back in the day, I used to write articles for MSDN, and I started up this column called “Coding 4 Fun” (the name lives on today along with some of the same spirit). The premise was that I would write about code I wrote for my own personal use. An app to sync photos from my computer to my mother’s so that she would get updates of the kid’s pictures. A remote control using my Pocket PC (yep, that was a while ago). You get the idea.

That mostly all stopped when I joined the Channel 9 team. I didn’t just stop writing articles, I mostly stopped writing code for any reason other than work. Perhaps that’s a bad thing, but either way … no more writing about code for a few years.

A month or so ago though, I was searching the internet for a solution to a problem for my wife Laura. She writes articles for ParentMap (a local parenting publication here in the Seattle area), and as part of that job she records interviews with people on digital recorder. I noticed that after recording the interview, she would spend a long time transcribing the interview from the sound file into text. You can probably understand how time-consuming that is using something like Windows Media Player. Press play, type for a bit, use your mouse to move the slider back because you missed something, go back to typing, slide it back, pause it, play it… it took ages to turn the audio into text. My first thought was some sort of speech recognition, but:

  • since she would be quoting people it had to be exact, not close and
  • the results I experienced running a few of her recordings through a few apps ranged from hilarious to terrible.

So I downloaded a bunch of apps, free or trial versions, that seemed to be what I wanted … an app for you to control audio playback while you typed up the transcript. Some of the high-priced ones, meant for legal or medical transcription, looked perfect… but Laura is not getting paid doctor or lawyer money to write these articles, so paying those types of prices seemed very wrong. Instead I decided to write something myself. This is the result of maybe 30-45 minutes work, and most of that was spent fiddling with different key bindings for controlling the playback.

AudioTranscription.png
The key bindings I settled on were designed to allow you to keep your hands on the keyboard during the entire transcription.

  • Tab pauses the audio, press it again to jump back 5 seconds (configurable) and resume playback
  • \ (which happens to be in a good spot on my keyboard and my wife’s … opposite side but same spot as Tab) just jumps back 5 seconds without pausing.

It works really well for her purposes; well enough that I thought I should post it. So here you go, it is a Visual Studio 2012 package, written in C# and posted here in a zip.

If you just want to run it, I’m not offering free support but you can click on this link and follow the instructions from there: http://duncanmackenzie.net/transcribe/publish.htm

Code Metrics in Visual Studio 2008 and the EvNet project

I don’t know if this is good or bad, but I thought it was neat that I could right-click the main project (excluding all our client script and HTML) that runs behind on10.net, pick code metrics and see cool #s like “23,442 lines of code” 🙂

 

Lately though, I’ve seen us reducing that number while adding features, so this might the highest result I’ll ever see for this project 🙂

Trackbacks and URL matching

I recently noticed a bug in the trackback code on Channel 10, some sites were failing to send us trackbacks, even though we were receiving trackbacks from other sources and those sites were happily trackbacking (I’m just annoying the spell checker today) other blogs.

Turns out the problem appears to be in our RDF block on our blog pages. On a page like this, the RDF block contains the following element:

dc:identifier="http://on10.net/Blogs/tina/exclusive-video-first-look-at-the-xbox-elite/"

This uses the permalink URL that we provide for this page, but of course there are several other urls that work to get to the same resource including

  • http://on10.net/Blogs/tina/exclusive-video-first-look-at-the-xbox-elite/default.aspx,
  • http://www.on10.net/Blogs/tina/exclusive-video-first-look-at-the-xbox-elite/ and
  • http://www.on10.net/Blogs/tina/exclusive-video-first-look-at-the-xbox-elite/default.aspx

When a client, some other blog or blog posting software, goes to auto-discover our trackback URL they try to match the dc:identifier to whatever url they used in their post. So, if they didn’t use the one we’ve chosen for our dc:identifier, then they don’t find our trackback info, they don’t send the trackback, and we don’t get the trackback.

This sucks, but what is the right way to handle it? Add four distinct RDF blocks? Or is there some way to include all four URLs in the one RDF block?

Just spent way too much time fixing VB code coloring on MSDN2

You may have already noticed this, but the current build of MSDN2 has a bug in the way it colors VB code snippets, as you can see here (scroll down, there are quite a few problems in the code snippet coloring, see how many you can spot!)… turns out the code wasn’t handling comments right, text in quotes, and it didn’t have a full list of the VB keywords (so MsgBox was not recognized, for example). I’ve fixed it all up now (I think) so that code will work its way through review and test then get added to some not-too-distant update of the site code… but for now, here is the revised output for those particular code samples.

Broken

' Imports statements must be at the top of a module.
Imports Microsoft.VisualBasic.CallType
Sub TestCallByName1()
    'Set a property.
    CallByName(TextBox1, "Text", CallType.Set, "New Text")

    'Retrieve the value of a property.
    MsgBox(CallByName(TextBox1, "Text", CallType.Get))

    'Call a method.
    CallByName(TextBox1, "Hide", CallType.Method)
End Sub
Public Sub TestCallByName2()
    Dim col As New Collection()

    'Store the string "Item One" in a collection by 
    'calling the Add method.
    CallByName(col, "Add", CallType.Method, "Item One")

    'Retrieve the first entry from the collection using the 
    'Item property and display it using MsgBox().
    MsgBox(CallByName(col, "Item", CallType.Get, 1))
End Sub

Fixed

' Imports statements must be at the top of a module.
Imports Microsoft.VisualBasic.CallType
Sub TestCallByName1()
    'Set a property.
    CallByName(TextBox1, "Text", CallType.Set, "New Text")

    'Retrieve the value of a property.
    MsgBox(CallByName(TextBox1, "Text", CallType.Get))

    'Call a method.
    CallByName(TextBox1, "Hide", CallType.Method)
End Sub
Public Sub TestCallByName2()
    Dim col As New Collection()

    'Store the string "Item One" in a collection by 
    'calling the Add method.
    CallByName(col, "Add", CallType.Method, "Item One")

    'Retrieve the first entry from the collection using the 
    'Item property and display it using MsgBox().
    MsgBox(CallByName(col, "Item", CallType.Get, 1))
End Sub