Bookmark changes between 5.1 and Stereo audio?

Inspired by this, I coded a little awk script to generate a VideoRedo chapter file from the ffprobe output. Here it is for anyone interested. It assumes 25 fps, although that's not really important. It's been working so far and gets you near the start and end of ads - useful for Channel 4 HD stuff anyway.
C-like:
'
BEGIN{ FS=","; st=-1;}
    {if (st==-1) {st=$1; ch=$2}}
    {t=$1-st}
ch!=$2 {
    h=int(t/3600);
    m=int((t-h*3600)/60);
    s=int(t-h*3600-m*60);
    f=(t-(int(t)))*25;
    printf(%pf%,h,m,s,f);
    ch=$2
}'
 
I have been trying some experiments with the cropping phase (I haven't looked at the detection part yet) and have come up with a basic, initial, Jim script version that uses bookmarks to specify the crop points.
  • This can crop a 2:13 5GB HD movie in 32 minutes compared to 10.5 min for nicesplice. It does do a cleaner job but the speed isn't too bad and would be practical as a queued process.
  • The exec could easily be extended to take a list of crop point from silence, or changes of audio mode from ffprobe but I want to test the basic function first
  • I tried to use the ffconcat format but I just couldn't get it to work, It appear to ignore the inpoint/outpoint/duration option and run very slowly. Pity since it appears that it should do what we need :(
  • My exec uses a named pipe (FIFO) to connect the output of the segment extraction to the input of the concatenation thread.
  • .nts file generation runs afterwards but with a bit more plumbing could run as a pipe in parallel
  • It is very important that the ffmpeg -ss options precedes the -i parameter, when placed after the process takes twice as long to run!
  • The reason the output was reported as encrypted is that to determine whether a recording is encrypted is that the Humax (and stripts -E) check the PAT table in the recording and check whether the tableid is decrypted AND whether the Service id from the .hmt is contained in the PAT. The second check is not made when there is no hmt which explains why the recording plays when there is no hmt and fails when there is.
    ffmpeg builds a new PAT in the output and doesn't copy the service id or other contents from the input PAT
  • Since I couldn't spot a way to make ffmpeg copy the PAT I chose the easier option of changing the hmt to suit
    exec hmt "+patch16=0x0488:1" "$hmtfn.hmt" does the trick (ffmpeg seems to always use 1 in a very limited sample)
    I also use patch to update end time and duration fields in the hmt
  • I set bookmarks at crop -5 on the output to make it simple to check the crops.
Jim Code:
#!/mod/bin/jimsh

# Very basic crop test using ffmpeg based on the ideas presented by florca
# in https://hummy.tv/forum/threads/bookmark-changes-between-5-1-and-stereo-audio.9800/
# initial version only uses bookmark as source of crop points
# To be expanded in future to use lists of timestamps from ad-detection
# Author: MymsMan based on Florca

source /mod/webif/lib/setup
require ts.class system.class safe_delete
set ::loglevel 2
set ::logfd "stdout"

proc log {msg {level 1}} {
        if {$level > $::loglevel} return
        puts $::logfd "[\
                clock format [clock seconds] -format "%d/%m/%Y %H:%M:%S"\
                ] CT- $msg"
        flush $::logfd
}
proc set_HMT_durn {hmtfn start durn} {
            # Update recording end & stored recording time in hmt file
            exec hmt "+patch32=0x284:$($durn+$start)"  "$hmtfn.hmt"
            exec hmt "+patch32=0x288:$durn"  "$hmtfn.hmt"
            # Fake out the Service id since ffmpeg doesn't copy pat
            exec hmt "+patch16=0x0488:1"  "$hmtfn.hmt"
}


# Start timing
set st_timer [clock milliseconds]

# Get file name from params and open ts
set file [lindex $argv 0]
set ts [ts fetch "$file"]
if {$ts==0} {
  log "Can't open $file"
  return 1
}

# Get bookmark list
set crops [$ts bookmarks 1]
set dur $([$ts get end]-[$ts get start])

# Add end of recording if odd number
if {[llength $crops]%2} {lappend crops $dur}
if {[llength $crops]==0} {
  log "No crop points"
  return 1
}
log "Crop points $crops"

set root [file rootname $file]
set tgt "$root-crptst"
set tgtf "$tgt.m2ts"

# Open pipe for output (to prevent EOF being generated after each segment)
set pipeout "$root-pipeout.m2ts"
catch {exec mkfifo $pipeout}
set OutFD [open $pipeout w+]
log "Opened output pipe $pipeout" 2

# Set up output file
if {[file exists "$tgt.m2ts"]} {
  safe_delete "$tgt.m2ts" croptest
}
if {[file exists "$tgt.ts"]} {
  safe_delete "$tgt.ts" croptest
}

# Run ffmpeg to concatenate segments from pipe
set outpid [exec {*}"nice -n 19 ffmpeg -nostats -loglevel fatal -i {$pipeout} -async 1 -fflags +genpts -y -c copy {$tgtf}  &"]
log "Started concat process pid: $outpid" 2

set durn 0
set BMoff -5
set newBM {}
# loop through time pairs
loop seg 0 [llength $crops] 2 {
  set beg [lindex $crops $seg]
  set end [lindex $crops $($seg+1)]

  set durn $($durn +$end -$beg)
  lappend newBM $(round($durn)+$BMoff)
  # start clock
  set st_copy [clock milliseconds]
  log "Segment: $($seg/2 +1) $beg-$end $($end -$beg) seconds starting" 2

  # Copy source section
  exec {*}"ffmpeg -hide_banner -loglevel fatal -nostats -ss $beg  -i {$file}  -c copy  -y -async 1 -t $($end -$beg) {$pipeout}   2>@$::logfd"

  # stop clock & report
  set end_copy [clock milliseconds]
  log "Segment: $($seg/2 +1) $beg-$end copied in $(($end_copy-$st_copy)/1000) seconds" 1
}

# close pipes
close $OutFD
file delete $pipeout

# Create new HMT
file rename "$tgt.m2ts" "$tgt.ts"
file copy -force "$root.hmt" "$tgt.hmt"
set crpts [ts fetch $tgt.ts]
$crpts settitle "[$crpts get title] -Crop test"
$crpts setbookmarks $newBM
set_HMT_durn "$tgt" [$crpts get start] $durn

# Stop clock and report
set end_timer [clock milliseconds]
log "File $file cropped in $(($end_timer-$st_timer)/1000) seconds" 0


if {[file exists /mod/bin/sidecar]} {
  set sc_timer [clock milliseconds]
  exec {*}"/mod/bin/sidecar -n {$tgt} >@$logfd "
  set esc_timer [clock milliseconds]
  log "New nts now built in $(($esc_timer-$sc_timer)/1000) seconds" 0
}
close $logfd
return 0
Example run
Code:
humax /mnt/hd2/My Video/[NA] # abduco -A crop time /mod/git/croptest  Sherlock_Holmes_20200724_2245-decr.ts
10/08/2020 13:57:29 CT- Crop points 22 1118 1435 3507 3802 5299 5547 6477 6752 7997
10/08/2020 13:57:29 CT- Opened output pipe Sherlock_Holmes_20200724_2245-decr-pipeout.m2ts
10/08/2020 13:57:30 CT- Started concat process pid: 27395
10/08/2020 13:57:30 CT- Segment: 1 22-1118 1096 seconds starting
10/08/2020 14:02:15 CT- Segment: 1 22-1118 copied in 284 seconds
10/08/2020 14:02:15 CT- Segment: 2 1435-3507 2072 seconds starting
10/08/2020 14:10:30 CT- Segment: 2 1435-3507 copied in 495 seconds
10/08/2020 14:10:30 CT- Segment: 3 3802-5299 1497 seconds starting
10/08/2020 14:17:13 CT- Segment: 3 3802-5299 copied in 402 seconds
10/08/2020 14:17:13 CT- Segment: 4 5547-6477 930 seconds starting
10/08/2020 14:21:51 CT- Segment: 4 5547-6477 copied in 278 seconds
10/08/2020 14:21:51 CT- Segment: 5 6752-7997 1245 seconds starting
10/08/2020 14:29:30 CT- Segment: 5 6752-7997 copied in 458 seconds
10/08/2020 14:29:30 CT- File Sherlock_Holmes_20200724_2245-decr.ts cropped in 1921 seconds
10/08/2020 14:48:18 CT- New nts now built in 1127 seconds
real    50m 49.29s
user    24m 59.11s
sys     2m 33.05s
crop: session terminated with exit status 0
 
The reason the output was reported as encrypted is that to determine whether a recording is encrypted is that the Humax (and stripts -E) check the PAT table in the recording and check whether the tableid is decrypted AND whether the Service id from the .hmt is contained in the PAT. The second check is not made when there is no hmt which explains why the recording plays when there is no hmt and fails when there is.
That seems idiotic to me.
 
This is Humax code we are talking about
I fully acknowledge that, but there must have been a rationale for it which escapes me. Further, AF must have been able to work out what it does in order to simulate that in stripts. That is equally remarkable if it has no rationale, and what would be the point - I presume the desire is to detect whether a recording is encrypted, not whether Humax thinks it is encrypted.
 
Inspired by this, I coded a little awk script to generate a VideoRedo chapter file
I have been trying some experiments with the cropping phase (I haven't looked at the detection part yet) and have come up with a basic, initial, Jim script version that uses bookmarks to specify the crop points.
Thanks both for these, which answer questions I've been thinking about on ways to break the functions down into multiple, selectable steps, both to cater for running on different platforms and for different programme types. Will definitely try switching the order of the -ss / -to and -i ffmpeg parms - another example of the obscurity of ffmpeg documentation!
I've been diverted by other things in the recent weather (mainly a small boat...) so haven't progressed much, but very attracted by the idea of using HMT bookmarks as a standard way to signal cut points - either for direct action or as input to VRD via Chapter Marks (I'm also toying with the idea of further metadata insertion after conversion to .MP4, such as adding the HMT description as a Synopsis and parsing it for a valid year when the Genre is film, to then change the file name for auto-cataloguing via Emby / IMDB).
Quick question relating back to the detection phase - will HMT accept non-integer bookmarks (eg 123.5678 seconds) and retain them? I'm quite keen to maintain the precise the PTS timestamps signalled by the audio channel-count change if possible... Will experiment when I get back to this, but good to know if anyone has a definite answer?
I tried to use the ffconcat format but I just couldn't get it to work, It appear to ignore the inpoint/outpoint/duration option and run very slowly. Pity since it appears that it should do what we need
That's wierd - for me it was running fast and recognising inpoint / outpoint settings, but producing cuts in different (wrong) locations compared to the way I tried first. I had a few tries at getting it working properly but could never get cuts in the right places - as you say if this could be made to work it would make the whole process a lot slicker!
 
... Quick question relating back to the detection phase - will HMT accept non-integer bookmarks (eg 123.5678 seconds) and retain them? I'm quite keen to maintain the precise the PTS timestamps signalled by the audio channel-count change if possible... Will experiment when I get back to this, but good to know if anyone has a definite answer? ...
https://wiki.hummy.tv/wiki/HMT_File_Format said:
 
Quick question relating back to the detection phase - will HMT accept non-integer bookmarks (eg 123.5678 seconds) and retain them? I'm quite keen to maintain the precise the PTS timestamps signalled by the audio channel-count change if possible...
No. only integers but there is nothing to stop you passing a list of time stamps into another programme - nicepslice currently supports 10th second resolution time stamps and that is what detectads uses when cropping internally rather than bookmarks - given 25fps you don't really need 4 decimal place to identify a frame and the software moves to a key frame anyway.
I hadn't bothered to code more complex parameter parsing into the initial version - not suggesting that BM were the best way.

That's wierd - for me it was running fast and recognising inpoint / outpoint settings, but producing cuts in different (wrong) locations compared to the way I tried first. I had a few tries at getting it working properly but could never get cuts in the right places - as you say if this could be made to work it would make the whole process a lot slicker!
Can you give an example of the ffmpeg command you were using and I will try and see where we were both going wrong.
I fully acknowledge that, but there must have been a rationale for it which escapes me. Further, AF must have been able to work out what it does in order to simulate that in stripts. That is equally remarkable if it has no rationale, and what would be the point - I presume the desire is to detect whether a recording is encrypted, not whether Humax thinks it is encrypted.
If the 1-byte PAT table id is not what you expect it to be it indicates that the recording is encrypted but, because we are not using Enigma cyphers, the converse is not true. You need to check another piece of 'known' information to see if the data really has been decrypted - presumably the service id is what Humax chose since that cant change mid recording unlike programme id. If you don't have an hmt then I guess the humax will check the PAT tableid in each PAT it encounters
 
Last edited:
I've spent a while playing with assorted combinations of ffmpeg options and as usual I am still baffled and confused 😖

I all seems to depend on the input file type.

when using humax native .ts files -ss works as an input ffmpeg option but -t and -to don't - they must be used on the output side.
ffconcat file options inpoint, outpoint, duration don't work

when using .mp4 or .m2ts all of the above options do work correctly

This is not related to out of date ffmpeg on humax, same occurs using a current windows build

A .m2ts output file from ffmpeg can be simply renamed .ts and played on the humax (after tweaking service id in humax hmt)

A humax .ts cannot OTOH be simply renamed .m2ts and used as input to ffmpeg, you have to copy with ffmpeg instead before you can use the selection options . 😭
 
I've spent a while playing with assorted combinations of ffmpeg options and as usual I am still baffled and confused 😖

I all seems to depend on the input file type.
.......
A .m2ts output file from ffmpeg can be simply renamed .ts and played on the humax (after tweaking service id in humax hmt)

A humax .ts cannot OTOH be simply renamed .m2ts and used as input to ffmpeg, you have to copy with ffmpeg instead before you can use the selection options . 😭
I've no real evidence, but is this maybe related to LATM audio? Does the ffmpeg Copy convert the LATM to ADTS by default? Does the behaviour change between HD & SD material?
 
I get totally bemused by the alphabet soup of acronyms for video and audio types and know nothing about the differences between them

I present SD and HD streams before and after ffmpeg copy to .m2ts

SD before:
Code:
Input #0, mpegts, from 'BBCNewsSD.ts':
  Duration: 00:32:30.38, start: 37012.410267, bitrate: 3754 kb/s
  Program 4163
    Metadata:
      service_name    : BBC ONE South
      service_provider:
    Stream #0:0[0x65]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv, top first), 704x576 [SAR 16:11 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x66](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, fltp, 256 kb/s
    Stream #0:2[0x6a](eng): Audio: mp3 ([3][0][0][0] / 0x0003), 0 channels, fltp (visual impaired) (descriptions) (dependent)
    Stream #0:3[0x69](eng): Subtitle: dvb_subtitle ([6][0][0][0] / 0x0006)
    Stream #0:4[0x98]: Data: bin_data ([6][0][0][0] / 0x0006)
    Stream #0:5[0x1c21]: Unknown: none ([11][0][0][0] / 0x000B)
    Stream #0:6[0x1c33]: Unknown: none ([11][0][0][0] / 0x000B)
    Stream #0:7[0x1bbf]: Unknown: none ([5][0][0][0] / 0x0005)
    Stream #0:8[0x1bc1]: Unknown: none ([5][0][0][0] / 0x0005)

SD after ffmpeg -i BBCNewsSD.ts -t 30 -c copy BBCNewsSD.m2ts
Code:
Input #0, mpegts, from 'BBCNewsSD.m2ts':
  Duration: 00:00:30.10, start: 1.400000, bitrate: 2567 kb/s
  Program 1
    Metadata:
      service_name    : Service01
      service_provider: FFmpeg
    Stream #0:0[0x100]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv, top first), 704x576 [SAR 16:11 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x101](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, fltp, 256 kb/s


HD Before
Code:
Input #0, mpegts, from 'GardenRescueHd.ts':
  Duration: 00:10:33.55, start: 59819.509500, bitrate: 5686 kb/s
  Program 17472
    Metadata:
      service_name    : BBC TWO HD
      service_provider:
  Program 17540
    Metadata:
      service_name    : BBC ONE HD
      service_provider:
    Stream #0:0[0x19c9]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x19ca](eng): Audio: aac_latm (LC) ([17][0][0][0] / 0x0011), 48000 Hz, stereo, fltp
    Stream #0:2[0x19ce](eng): Audio: aac_latm (HE-AACv2) ([17][0][0][0] / 0x0011), 48000 Hz, stereo, fltp (visual impaired) (descriptions) (dependent)
    Stream #0:3[0x19cd](eng): Subtitle: dvb_subtitle ([6][0][0][0] / 0x0006)
    Stream #0:4[0x1c86]: Unknown: none ([11][0][0][0] / 0x000B)
    Stream #0:5[0x1c97]: Unknown: none ([11][0][0][0] / 0x000B)
    Stream #0:6[0x1bc4]: Unknown: none ([5][0][0][0] / 0x0005)
    Stream #0:7[0x1bc6]: Unknown: none ([5][0][0][0] / 0x0005)

HD After ffmpeg -i GardenRescueHd.ts -t 30 -c copy GardenRescueHd.m2ts
Code:
Input #0, mpegts, from 'GardenRescueHd.m2ts':
  Duration: 00:00:30.22, start: 1.400000, bitrate: 4209 kb/s
  Program 1
    Metadata:
      service_name    : Service01
      service_provider: FFmpeg
    Stream #0:0[0x100]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x101](eng): Audio: aac_latm (LC) ([17][0][0][0] / 0x0011), 48000 Hz, stereo, fltp

As far as I can see apart from stripping out subtitles and audio-desrciption (which some users probably need kept) their don't seem to be any transformations going on
So I am still not sure why some ffmpeg options don't work on .ts files
 
I've never found a way to get ffmpeg to convert LATM to ADTS (without re-encoding), although I think I saw some requests in the forums for the facility. It certainly doesn't do it when copying. I guess there might be some convoluted set of filters that could do it. (And Handbrake can't pass LATM through or remove LATM either ☹)

By the way adding -map 0 to the ffmpeg would have copied all the streams rather than one video + one audio. (edited to add this usage)
 
Last edited:
I present SD and HD streams before and after ffmpeg copy to .m2ts
So.. The HD ffmpeg output still has AAC-LATM audio so that's not the reason. Maybe it's re-writing the timestamps? I think the reason why my ffmpeg -ss / -to cuts were working directly on Humax output with no intermediate copy step is that I was putting those parms after the -i xxx.ts rather than before. Need to run some more tests...
I've never found a way to get ffmpeg to convert LATM to ADTS (without re-encoding)
vlc will do this quickly and (for me...) reliably. Here's a working command on Linux to convert .ts to an .mp4 container, stripping the Subtitle track and with implicit conversion of LATM to ADTS audio (NB the '/" quoting):
Code:
cvlc --no-repeat --no-audio --no-video --no-sout-spu --no-loop -I dummy "aaa (yyyy).ts" --play-and-exit --sout='#transcode{}:std{access=file,mux=mp4,dst="aaa (yyyy).mp4"}'
and on Windows...
Code:
"%PROGRAMFILES%\VideoLAN\VLC\vlc.exe" --no-repeat --no-sout-spu --no-loop -I dummy "aaa (yyyy).ts" --play-and-exit --sout="#transcode{}:standard{access=file,mux=mp4,dst=aaa(yyyy).mp4}"
 
I think the reason why my ffmpeg -ss / -to cuts were working directly on Humax output with no intermediate copy step is that I was putting those parms after the -i xxx.ts rather than before. Need to run some more tests...
Yes, but it doesn't explain why you were able to use ffconcat while I wasn't.
The reason it would be good to use -t/-to before -i is that it would give us alternative to ffconcat or physically extracting the segments,
we should be able to use multiple -ss n.n -to m.m -i xx,ts triplets on a single ffmpeg command
 
I've spent a while playing with assorted combinations of ffmpeg options and as usual I am still baffled and confused 😖

I all seems to depend on the input file type.

when using humax native .ts files -ss works as an input ffmpeg option but -t and -to don't - they must be used on the output side.
ffconcat file options inpoint, outpoint, duration don't work

when using .mp4 or .m2ts all of the above options do work correctly

This is not related to out of date ffmpeg on humax, same occurs using a current windows build

A .m2ts output file from ffmpeg can be simply renamed .ts and played on the humax (after tweaking service id in humax hmt)

A humax .ts cannot OTOH be simply renamed .m2ts and used as input to ffmpeg, you have to copy with ffmpeg instead before you can use the selection options . 😭
Are these problems related to the stream start point? When copied by ffmpeg the start of the stream is set to zero (actually 1.4 seconds, the parameter '-muxdelay 0' as an output option will set the start to zero). The original stream start varies considerably: the commands may work as expected if you add the actual stream start value to your offsets.
 
Are these problems related to the stream start point? When copied by ffmpeg the start of the stream is set to zero (actually 1.4 seconds, the parameter '-muxdelay 0' as an output option will set the start to zero). The original stream start varies considerably: the commands may work as expected if you add the actual stream start value to your offsets.
That makes sense! When I was calculating the cut points using PTS timestamps I needed to take the PTS time value (as reported by pkt_pts_time from ffprobe) of the first frame and subtract this from the offsets of subsequent reported pkt_pts_time values. I think an ffmpeg copy step with -muxdelay 0 (and maybe -r?) will line everything up nicely with re-written timestamps which stand a decent chance of working with any of the -ss / -to and concat options??
 
Are these problems related to the stream start point? When copied by ffmpeg the start of the stream is set to zero (actually 1.4 seconds, the parameter '-muxdelay 0' as an output option will set the start to zero). The original stream start varies considerably: the commands may work as expected if you add the actual stream start value to your offsets.
Possibly but that doesn't fully explain the symptoms, -ss takes offsets from start of recording and not from the PTS time stamp and does work before -i, it would be very inconsistent if -to worked differently.
-t shouldn't be affected by the starting PTS time since it is an absolute value
I think an ffmpeg copy step with -muxdelay 0 (and maybe -r?) will line everything up nicely with re-written timestamps which stand a decent chance of working with any of the -ss / -to and concat options??
It will undoubtedly work, my experiments showed that but it takes a considerable time to copy a 5GB 2 hour recording even when processing is overlapped using pipes.
To achieve reasonable performance we need to minimise the number of passes through the entire recording. Ideally ffmpeg should work as documented without needed to copy the recording first and cropping should be possible with a single pass.
 
Possibly but that doesn't fully explain the symptoms, -ss takes offsets from start of recording and not from the PTS time stamp and does work before -i, it would be very inconsistent if -to worked differently.
-t shouldn't be affected by the starting PTS time since it is an absolute value
I'm not sure if this is relevant, but if you set both -ss and -to as output options with ffmpeg it works as expected, i.e. the section copied starts at the 'ss' value and ends at the 'to' value. However, if you set -ss as an input option, the -to option acts like -t, i.e. the section copied starts at the 'ss' value with the 'to' value used as the duration.
 
By the way adding -map 0 to the ffmpeg would have copied all the streams rather than one video + one audio. (edited to add this usage)
In simple cases adding '-map 0' works but in the examples in post #71, that command will cause the process to fail on two counts. For some reason, BBC broadcasts have extra streams which ffmpeg can't decode. This is easily fixed by adding '-ignore_unknown' to the output side of the command line.
The audio description stream is also a problem as ffmpeg only decodes the first five seconds of each stream by default. This is often too brief to find any audio in that stream to decode, and it will be assumed to be a zero channel mp3 stream which it can't copy. This is often fixed by adding something like '-probesize 60M -analyzeduration 60M' as input parameters. This will analyse the first 60 MB/ 60 seconds of the recording, whichever comes first. However, sometimes there is just an empty audio stream when there is no audio description track and I have not found a way of automatically coping with this. In these cases, I add '-map 0:0 -map 0:1 -map 0:3' to the output of the command line instead of '-map 0'. This copies the video, main audio and subtitle streams.
 
Back
Top