Can ffmpeg write comskip info into the video file?

MCEBuddy has the ability to embed chapter markers into the video file based on Comskip’s analysis. I like this because I don’t trust Comskip’s accuracy enough to actually cut the commercials, and Plex can’t read .edl files.

I am on a seemingly never-ending quest for the ideal PMS machine. I have a power hungry Windows 10 machine that I can’t leave on 24/7 and a NAS that can’t transcode. I’ve even tried the Nvidia SHIELD, but that has been a total failure on multiple levels and so far doesn’t support the DVR. I’m thinking about setting up an Intel NUC and just running Ubuntu, but I’m afraid of losing MCEBuddy.

It looks like the combination of ffmpeg and comskip, along with Plex’s baked-in post-processing ability should be able to (mostly) replace MCEBuddy for me. But, as I asked in the subject, can ffmpeg create chapter markers in the video file itself, similar to MCEBuddy?

It should be possible, mkvmerge supports chapters.
I was looking into this the other day.
I just haven’t found a way to convert comskip’s EDL into a format mkvmerge wants

I found this tool called: VideoUpdater which says it will take an EDL input file, and directly make chapters in MKV files…

This thread on Comskip’s forums says that Comskip can create .xml files, which mkvmerge supports. Might be worth a try.

http://www.kaashoek.com/comskip/viewtopic.php?f=5&t=1457

Unfortunately the prior tool I linked to was an exe, and I wasn’t able to locate the source… This might be useful info on what mkvmerge looks for in an XML file:
https://mkvtoolnix.download/doc/mkvmerge.html#mkvmerge.segmentinfo

Now the question is if the XML file that Comskip produces is compatible with the XML format that mkvmerge expects? I’m thinking that they are different…

So from here:
https://mkvtoolnix.download/doc/mkvmerge.html#mkvmerge.chapters

It state it want the xml in this format:

<!DOCTYPE Chapters SYSTEM "matroskachapters.dtd">
<Chapters>
  <EditionEntry>
    <ChapterAtom>
      <ChapterTimeStart>00:00:30.000</ChapterTimeStart>
      <ChapterTimeEnd>00:01:20.000</ChapterTimeEnd>
      <ChapterDisplay>
        <ChapterString>A short chapter</ChapterString>
        <ChapterLanguage>eng</ChapterLanguage>
      </ChapterDisplay>
      <ChapterAtom>
        <ChapterTimeStart>00:00:46.000</ChapterTimeStart>
        <ChapterTimeEnd>00:01:10.000</ChapterTimeEnd>
        <ChapterDisplay>
          <ChapterString>A part of that short chapter</ChapterString>
          <ChapterLanguage>eng</ChapterLanguage>
        </ChapterDisplay>
      </ChapterAtom>
    </ChapterAtom>
  </EditionEntry>
</Chapters>```

After setting Comskip to output XML it returns:
```<?xml version="1.0" encoding="utf-8" ?>
<root>
  <commercial start="0.967692" end="2.602655" />
  <commercial start="303.636736" end="422.055056" />
  <commercial start="723.823175" end="842.241483" />
  <commercial start="1652.918049" end="1797.395655" />
 </root>```

So it's close,  but not there yet

I hacked something together quickly to do exactly this, and it seems to work fine (except I can’t find an easy way to skip to next chapter on Apple TV client),

#!/bin/sh

DIR=`mktemp -d`

/usr/local/bin/comskip -n --output=$DIR -v1 --zpchapter "$1"  

INPUTFILE=$DIR/*.chp
CHAPTERS=$DIR/chapters.txt
TEMPMKV=$DIR/merged.mkv

echo $INPUTFILE
if [ -s $INPUTFILE ]
then
	cat $INPUTFILE | perl /home/media/scripts/convert_chapters.pl > $CHAPTERS
	if [ -s $CHAPTERS ]
	then
		mkvmerge --chapters $CHAPTERS -o $TEMPMKV "$1"
		mv $TEMPMKV "$1"
	fi
fi

rm -rf $DIR

and then I have the convert_chapters.pl script looking something like this

#!/usr/bin/perl

use POSIX qw{strftime};

my $chapterno = 1;

while (<>) {
	my @words = split /^AddChapterBySecond\(([0-9]+),(.*)\)$/;
	if ($words[2] eq "Show Segment") { 
		printf "CHAPTER%02d=%s.000

“, $chapterno, strftime(”%H:%M:%S", gmtime($words[1]));
printf "CHAPTER%02dNAME=Commercial %d
", $chapterno, $chapterno;
$chapterno++;
}
}

it will basically create a chapter mark for the END of each detected commercial block.

Nice work @“ml@kg6sed.com”
I’m playing with now, but using mkvpropedit, instead of mkvmerge

# mkvmerge --chapters $CHAPTERS -o $TEMPMKV "$1"
/usr/bin/mkvpropedit "$1" --edit track:a1 --set language=eng --edit track:v1 --set language=eng --chapters $CHAPTERS
# mv $TEMPMKV "$1"

Wow, thanks, guys. This looks to be a bit beyond my level of scripting skill, but I’ll take a closer look later when I’m at home. ml@kg6sed.com, on the Apple TV, you should be able to access chapters in the swipe down (from the top) menu during playback. Granted, it’s not a single “skip” button press, but it’s pretty quick and painless. The UI puts a checkmark next to the chapter you’re currently on, so it’s easy to see where you are and select the next-in-line chapter.

Thanks for posting this ml@kg6sed.com.

I’ve added your scripts to my setup and will give it a try this afternoon.

Ahh, mkvpropedit looks like a much better way of doing it. Thanks for pointing it out.

@ml@kg6sed.com said:

Ahh, mkvpropedit looks like a much better way of doing it. Thanks for pointing it out.

NP, you did all the heavy lifting :slight_smile:

@ml@kg6sed.com said:

/usr/local/bin/comskip -n --output=$DIR -v1 --zpchapter "$1"  

I meant to ask before what does the -n and -v1 do in the above comskip line?

Ah, -v1 can be removed, I just used it for debugging purposes (verbose). The -n flag is to make it run nicer, ie, not use up all the CPU. I didn’t want comskip to take away CPU from transcoders. It may or may not be necessary. I find that on my particular machine it slows down the number of frames comskip processes per second from 450 to 350fps. Another option might be to launch comskip with a different priority.

I do seem to have some issues with mkvpropedit though. Sometimes it does not add the chapters in. I’m not sure why this is, so I’ll stick with mkvmerge for now, it seems to work every time.

@Ethrex Sorry for my ignorance but I thought Plex didn’t support chapters in MKV. Does it support it now? Do all client UI support them also? Including Xbox One? What is the experience like, i.e. can you skip forward to the next chapter?

A good majority of the Clients support skipping by Chapters
How this script works is it marks the end of each commercial group/break as a chapter \For the Xbox-One if Chapter are present the jump 10 min (back/forward) will navigate between chapters instead

D-Pad (regular)
← - skip back 10s
↑ - jump forward 10min (Chapters)
→ - skip forward 30s
↓ - jump back 10min (Chapters)

I took the logic from this thread and translated it into a Windows Batch File (below). From my experience, the chapter idea presented in the thread works. However, while getting this to work I endured a lot of pain:

  • I am finding if I stop a current recording in beta 2 of Plex DVR, no matter what the recording becomes corrupted and can only be played it back in VLC (even without post-processing). This didn’t happen in beta 1. This was annoying when trying to test post-processing.
  • On my machine it takes about as much time to comskip as it does to record. So for a 3 hour football game, the game isn’t available in Plex until 6 hours from the start of the recording. I would much prefer a solution that I can post-process after publishing such that when the file isn’t locked I can move my post-processed file into place. Or better yet, how about we just support EDL files already?
  • It appears that while Plex is doing the post-processing, the ‘tuner slot’ within Plex is taken up (basically, it shows 100% in the server status until post-processing is done). I didn’t do a lot of testing around this, this was just a mental note. Of course the concern is that if both tuners are blocked on post-processing, will it block a scheduled recording?
  • I found on the XBox One, the chapter symbols in the time bar don’t paint until I actually skip to that chapter. It would be nice to get a view of all the chapters without having to skip to them…
  • Of course, unlike something like this NextPVR setup, you cannot get Plex to do this while the content is being recorded.

In any case, here is the current version of my batch script:

@echo off
setlocal enabledelayedexpansion

set comskip=S:\Plex\DvrPostProcessing\comskip81_092\comskip.exe
set mkvpropedit=S:\Plex\DvrPostProcessing\mkvtoolnix\mkvpropedit.exe

set comskiptemp=%~dp1comskip.tmp
set inputmkv=%~f1
set comskipchp=%comskiptemp%\%~n1.chp
set mkvpropchp=%comskipchp%.tmp

if exist "%comskiptemp%" rmdir /s /q "%comskiptemp%"
mkdir "%comskiptemp%"
"%comskip%" -n --output="%comskiptemp%" -v1 --zpchapter "%inputmkv%"

set chapternum=0
for /f "usebackq tokens=1,2,3 delims=(,)" %%a in (`type "%comskipchp%"`) do (
    set offset=
    if /i "%%a"=="AddChapter" if /i "%%c"=="Show Segment" set offset=%%b
    if /i "%%a"=="AddChapterBySecond" if /i "%%c"=="Show Segment" set offset=%%b
    if /i not "!offset!"=="" (
        set /a chapternum=!chapternum! + 1
        set chapterlbl=0!chapternum!
        set chapterlbl=!chapterlbl:~-2!

        set /a hours=!offset! / 3600
        set /a mins=!offset! %% 3600 / 60
        set /a secs=!offset! %% 60
        set hours=0!hours!
        set hours=!hours:~-2!
        set secs=0!secs!
        set secs=!secs:~-2!
        set mins=0!mins!
        set mins=!mins:~-2!

        echo CHAPTER!chapterlbl!=!hours!:!mins!:!secs!.000>>"%mkvpropchp%"
        echo CHAPTER!chapterlbl!NAME=Segment !chapternum!>>"%mkvpropchp%"
    )
)

if %chapternum% GTR 0 (
    "%mkvpropedit%" "%inputmkv%" --edit track:a1 --set language=eng --edit track:v1 --set language=eng --chapters "%mkvpropchp%"
)

rmdir /s /q "%comskiptemp%"
endlocal

@Ethrex said:
Or better yet, how about we just support EDL files already?

Now there’s a thought… :slight_smile:

It is still the Beta, so I guess there is hope… right?

Something so simple that SageTV had it right years ago!

:frowning:

Anyone have a linux version of this script?

@“Dean Junk” said:
Anyone have a linux version of this script?

It’s the one marked Answered
See: https://forums.plex.tv/discussion/comment/1255591/#Comment_1255591