0

Using the VLC CLI, is there any way to play the last x seconds of each video in a playlist?

I am aware of:

--start-time= Start time

The stream will start at this position (in seconds).

--stop-time= Stop time

 The stream will stop at this position (in seconds).

--run-time= Run time

 The stream will run this duration (in seconds).

But without some fancy logic, none of this really does what I'd like.

This is for reviewing motion triggered video, where the last 15 seconds are so are often the most interesting for determining wether you want to watch or save the whole video.

  • I can't find a way to specify time relative to the end; maybe some (not-so-)fancy logic is a must to calculate absolute time for each file separately. This information may then be embedded in an m3u playlist as #EXTVLCOPT. What OS, shell and tools (ffprobe or such) are available to implement the logic and to create a playlist? Please edit the question and add this information. – Kamil Maciorowski Jul 6 '19 at 20:57
  • @KamilMaciorowski I am using MacOS and can honestly install pretty much any open source tool that will get the job done. The answer from @zx485 utilizing just ffmpeg and a few common shell utils seems to have gotten the job done from what I saw with my initial test earlier today. – spkane Aug 2 '19 at 3:15
1

If you also have ffmpeg installed, you can use the following script. It's simple and does not take care of boundary cases like videos shorter than 15 secs or defective files (You'd have to extend it). But apart from that, it plays the last 15 seconds of a file with VLC:

#!/bin/bash
secondsBeforeEnd=15
length=`ffmpeg -i "$1" 2>&1 | grep "Duration" | cut -f4 -d' ' | cut -f1 -d','`
secs=$(date "+%s" --date="$length")
adjSecs=$(echo "$secs - $secondsBeforeEnd" | bc)
adjTime=$(date +%T -d @$adjSecs)
finalSecs=$(date +"%S" -d @$adjSecs)
finalMins=$(date +"%M" -d @$adjSecs)
finalHour=$(date +"%H" -d @$adjSecs)
newStart=$(echo "$finalSecs + $finalMins*60 + $finalHour*3600" | bc)
echo "=============================="
echo "Original Length: $length"
echo "Adjusted Length: $adjTime"
echo "Starting time in seconds: $newStart"
echo "=============================="
vlc --start-time=$newStart "$1" "$2" "$3" "$4"

You can, of course, put this in a for loop.
Simple bash scripting abilities will suffice to do that (You should get the idea). I haven't found a way to retrieve the length of a video file from VLC, so I had to use ffmpeg.


A second possibility is to handle the playlist directly. You need an XSLT processor for this, like xsltproc(Linux/Ubuntu) or Saxon-HE(Linux/Windows):

For example, assume that you have a VLC playlist named play.xspf.
Then you apply this XSLT-1.0 stylesheet (named playlist.xslt) to the playlist:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:l="http://xspf.org/ns/0/">
    <xsl:output method="text" indent="no" />
    <xsl:variable name="beforeEnd" select="15" />

    <xsl:template match="text()" />    

    <xsl:template match="/">
        <xsl:text>#!/bin/bash</xsl:text>
        <xsl:text>&#xd;&#xa;</xsl:text>
        <xsl:apply-templates select="l:playlist/l:trackList/l:track" />
    </xsl:template>

    <xsl:template match="l:track">
        <xsl:variable name="startTime" select="substring-before(l:duration div 1000,'.') - $beforeEnd" />
        <xsl:if test="$startTime > 0">
            <xsl:text>vlc --start-time=</xsl:text>
            <xsl:value-of select="$startTime" />
            <xsl:text> </xsl:text>
            <xsl:value-of select="l:location" />        
            <xsl:text>&#xd;&#xa;</xsl:text>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

You can do this with

xsltproc playlist.xslt play.xspf

or

java -jar saxon9he.jar -xsl:playlist.xslt play.xspf

Its output is a bash script which will run the last 15 seconds of each file of the playlist or skip the file if it is shorter than 15 seconds.

If you're using Windows, simply remove the #!/bin/bash line (and adjust the rest to the batch file requirements, if necessary).

| improve this answer | |
  • Thank you. This worked well. On Mac OS X, I had to make sure to use GNU date, versus the build in BSD date, but otherwise things worked as expected. – spkane Aug 2 '19 at 1:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.