Skip to content

Commit

Permalink
Add embedded timecode metadata to generated MP4 (#30)
Browse files Browse the repository at this point in the history
Adds embedded timecode metadata support when generating MP4 files
  • Loading branch information
kris-sum authored May 17, 2023
1 parent 64abfd3 commit c8ba44d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
13 changes: 12 additions & 1 deletion ffmpegutil/ffmpeg.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,18 @@ func MuxAudioAndVideo(partition *ubv.UbvPartition, h264File string, aacFile stri
videoTrack.Rate = 1
}

cmd := exec.Command(getFfmpegCommand(), "-i", h264File, "-itsoffset", strconv.FormatFloat(audioDelaySec, 'f', -1, 32), "-i", aacFile, "-map", "0:v", "-map", "1:a", "-c", "copy", "-r", strconv.Itoa(videoTrack.Rate), "-y", "-loglevel", "warning", mp4File)
cmd := exec.Command(getFfmpegCommand(),
"-i", h264File,
"-itsoffset", strconv.FormatFloat(audioDelaySec, 'f', -1, 32),
"-i", aacFile,
"-map", "0:v",
"-map", "1:a",
"-c", "copy",
"-r", strconv.Itoa(videoTrack.Rate),
"-timecode", ubv.GenerateTimecode(videoTrack.StartTimecode, videoTrack.Rate),
"-y",
"-loglevel", "warning",
mp4File)

runFFmpeg(cmd)
}
Expand Down
22 changes: 22 additions & 0 deletions ubv/ubvfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"log"
"strconv"
"time"
"fmt"
)

const (
Expand Down Expand Up @@ -153,3 +154,24 @@ func guessVideoRate(durations [32]int) int {

return mostFrequent
}

/**
* Generates a timecode string from a StartTimecode object and framerate.
* The timecode is set as the wall clock time (so a clip starting at 03:45 pm and 13 seconds will have a timestamp of 03:45:13)
* Additionally, the nanosecond time value is rounded to the nearest frame index based on the framerate,
* so a 13.50000 second time is frame 16 on a 30 fps clip (frames are indexed from 1 onwards).
* So the clip will have a full timestamp of 03:34:13.16
*
* @param startTimecode The StartTimecode object to generate a timecode string from
* @param framerate The framerate of the video
* @return The timecode string
*/
func GenerateTimecode(startTimecode time.Time, framerate int) string {

var timecode string
// calculate timecode ( HH:MM:SS.FF ) from seconds and nanoseconds for frame part
timecode = startTimecode.Format("15:04:05") + "." + fmt.Sprintf("%02.0f", ((float32(startTimecode.Nanosecond()) / float32(1000000000.0) * float32(framerate)) + 1) )
// log.Println("Timecode: ", timecode)
// log.Printf("Date/Time: %s", videoTrack.StartTimecode)
return timecode
}
8 changes: 8 additions & 0 deletions ubvfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import (
"ubvremux/ubv"
)

func TestGenerateTimecode(t *testing.T) {
timecode := ubv.GenerateTimecode(time.Date(2023, time.Month(5), 16, 11, 58, 26, 500000000, time.UTC), 30)
log.Printf("Timecode Generated")
if timecode != "11:58:26.16" {
t.Errorf("Timecode generated is incorrect, got: %s, want: %s.", timecode, "11:58:26.16")
}
}

func TestCopyFrames(t *testing.T) {
ubvFile := "samples/FCECDA1F0A63_0_rotating_1597425468956.ubv"

Expand Down

0 comments on commit c8ba44d

Please sign in to comment.