Scripted conversion of HyperDeck Studio ProRes videos to x264 with burned-in timecode

This article discusses how to loop through a folder of source files, manipulating the audio tracks, suitably encoding the video and burning text and timecode in the video.

Recently I worked on a project where the output of a vision and sound mixer was recorded to a HyperDeck for later review. The setup was referenced to master clock timecode from a Signal Pulse Generator (SPG), so the HyperDeck fortunately also embedded the timecode as a metadata track in its ProRes recordings.

I received a request to generate viewable files from the ProRes source, and burning the timecode on-screen (as you see with film rushes/dailies) was considered a good consistent reference for notetaking and discussion.

The requirement was to accomplish this without needing to use expensive NLE software or traipse into the office each night to use an edit suite. This session was in a hired facility miles from my usual workplace and I only had a Windows 10 laptop for company. But all we need is FFmpeg and FFprobe...

First off, ProRes from HyperDecks. It happily records to ProRes but the file structure is slightly unusual - they contain 16 mono audio channels (in DNxHD mode they only record 2) and will obviously be the same video standard as your input signal - in my case, 1080p50. 

Remapping the mono channels to a single stereo pair is easy in FFmpeg. Video wise, you may need to deinterlace your source footage during conversion if you're working in an HD broadcast workflow. I recommend ffmpeg's bwdif algorithm for excellent, quick results and I explained optimal deinterlacing with bwdif in a previous post.

On the HyperDeck Pro 2 (and presumably the Studio 12G and above) the DNxHD220 codec is used, which doubles your output filesize vs. 4:2:2 ProRes LT (~220 Mbps vs. 105 Mbps). 

If you have a specific need to record DNxHD, consider I would still recording ProRes and transcoding. I recommend ProRes LT as a filesize, quality and compatibility compromise - unless you have multiple large SSDs to accommodate long recording sessions.

I didn't have access to many tools or NLE software in this situation, so had to work with what was available - FFmpeg and FFprobe on Windows work fine for this. Download a Git build from Zeranoe's site or consult the oracle.

The "without installer" version of MediaInfo is also invaluable - download it from their Windows builds page. Don't use the auto installer, it bundles IronSource adware which they do disclose. Instead consider donating a few quid if you find it's saved you time and energy.

I created a batch script to do the following:

  1. Starting in the parent folder, loop through files in a "source" subfolder
  2. Extract each file's frame timecode with ffprobe, saving in a file alongside for later use
  3. Create an "x264" subfolder (if not already existing)
  4. Do some filename and folder substitution/rewriting, changing generic "Capture0001", "Capture0002" names to something more meaningful
  5. Burn in the previously extracted per-frame timecode and also apply a static datestamp to the video
  6. Use FFmpeg's channel map feature to discard the unused audio pairs (as we only embedded one split leg stereo mix to the first SDI audio pair), and transcode to AAC at a usable quality
  7. Encode DXVA-compliant H.264 video (with FFmpeg's libx264) which would play on any device/phone/tablet with hardware acceleration
  8. Echo status back to the terminal while going through the loop

It's a bit rough and ready, there's comments for a few things through the script (though not fully commented). Caveats:

  1. For the sake of time, I resorted to manually editing references to days (the example script is the version for outputting files createed on 'day 8' of the shoot).
    You could instead parse the file path, extract the day number or other relevant variable from it then do a substitution to make the output naming fully automated.
  2. You must change the FFmpeg drawtext filter text and the outputfile:Capture substitution text so filenames are created correctly
  3. This only works on Windows due to various batch scripting-specific things (variables, substitutions and parameter extensions). You could adapt for Linux/Mac version without too much work.
  4. I've used a worker loop and I call labels (think subroutine) to do the encoding and finish cleanly once all source files are transcoded.
  5. This script should be a .bat file, accompanied by ffmpeg.exe and ffprobe.exe

My example script:

@echo Day 8 encoder
@echo don't forget to change drawtext as well as paths!
@echo off
@rem echo "%~dpn1"
@rem for %%a in ("*.mov") do (

for %%a in (source\*.mov) do (
echo --- Going in.
echo %%a 
  call :mainloop %%a
echo --- All files transcoded.
exit /b

@rem goto:eof

echo -- File being processed: %1
"%~dp0\ffprobe" -hide_banner -loglevel fatal -print_format default=nk=1:nw=1 -show_entries format_tags=timecode %1 > %1-timecode.txt
set /p rawtc= < %1-timecode.txt
echo raw timecode: %rawtc%
set escapedtc=%rawtc::=\:%
echo escaped timecode: %escapedtc%

echo filename before substitution: %1
set sourcefile=%1
set outputfile=%outputfile:source\=x264\%
set outputfile=%outputfile:Capture=Day8-Capture%
echo filename after substitution: %outputfile%
echo %outputfile%
@rem del %1-timecode
if not exist "x264" mkdir "x264"
"%~dp0\ffmpeg" -hide_banner -i "%1" -c:v libx264 -crf 20 -preset faster -profile:v high -level 4.1 -vf "format=yuv420p,drawtext=fontfile='C\:/WINDOWS/fonts/lucon.ttf':text='Day 8':fontsize=48:fontcolor=white@0.2:x=20:y=20,drawtext=fontfile='C\:/WINDOWS/fonts/lucon.ttf':text='TC\ ': timecode='%escapedtc%':rate=50:fontsize=64:fontcolor='white@0.75:x=(w-text_w)/2:y=h-th-20" -tune film -map_metadata 0 -c:a aac -b:a 192k -ar 48000 -map_channel 0.2.0 -map_channel 0.2.1 -ac 2 %outputfile%
echo -- Transcode done: %1 

There's a few messy comments and leftovers from prior tests. Hacking together stuff like this always reminds me of the various ways you can comment in batch scripts and how they behave differently.

Let me know if you find this useful, if you find an issue or if you can suggest a better way of doing any of this!

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via email. You can also subscribe without commenting.