Simple script to adjust times for subtitles in SRT format

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Post Reply
Message
Author
User avatar
puppy_apprentice
Posts: 299
Joined: Tue 07 Feb 2012, 20:32

Simple script to adjust times for subtitles in SRT format

#1 Post by puppy_apprentice »

I was showing some movies for my family on TV but noticed that subtitles aren't synchronized well with dialogs. So i've made a script:

Code: Select all

#!/bin/sh
# srted.sh by puppy_apprentice
# simple script to adjust times for subtitles in SRT format
# https://matroska.org/technical/specs/subtitles/srt.html
# usage: srted.sh srtfile delta skip

srtfile=$1 # file with subtitles in SRT format
delta=$2   # number of seconds
skip=$3    # start after subtitle number
n=1

# used grep for extra newline for read command
grep "" $srtfile | while read -r line
do
		if [[ $line =~ "-->" ]]
		then
			if [[ $n > $skip ]]
			then
				ft=$(date "+%s" -d "01/01/1970 ${line:0:8}")
				ft=$((ft+delta))
				st=$(date "+%s" -d "01/01/1970 ${line:17:8}")
				st=$((st+delta))
				line=${line/${line:0:8}/$(date +%T -d @$ft)}
				echo "${line/${line:17:8}/$(date +%T -d @$st)}"
			else
				echo "$line"
			fi
			n=$((n+1))
		else
			echo "$line"
		fi
done
Do we have in Puppy Land apps for subtitles editing/converting?

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#2 Post by MochiMoppel »

Doesn't seem to work properly with the srt sample of the matroska.org page

Sample srt text:

Code: Select all

1
00:02:17,440 --> 00:02:20,375
Senator, we're making
our final approach into Coruscant.

2
00:02:20,476 --> 00:02:22,501
Very good, Lieutenant.
With delta=2 and skip=0 it gives me this:

Code: Select all

1
00:02:19,440 --> 00:02:22,375
Senator, we're making
our final approach into Coruscant.

2
00:02:24,476 --> 00:02:22,501
Very good, Lieutenant.
Subtitle 1 is OK, subtitle 2 is not.

User avatar
puppy_apprentice
Posts: 299
Joined: Tue 07 Feb 2012, 20:32

#3 Post by puppy_apprentice »

LOL. For 10 movies and subtitles for them worked fine. I had luck :)

I think that switching two lines is enough:

Code: Select all

line=${line/${line:17:8}/$(date +%T -d @$st)}
echo "${line/${line:0:8}/$(date +%T -d @$ft)}"
Thx for feedback.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#4 Post by MochiMoppel »

I also noticed that delta does not accept split seconds. I can imagine that even a delay of 0.5 sec can be annoying, so I tried a quick & dirty variation that allows deltas up to nanosecond level:

Code: Select all

#!/bin/bash
srtfile=$1 # file with subtitles in SRT format 
delta=$2   # number of seconds (min 1, max 9 decimals)
skip=$3    # start after subtitle number

[[ $delta =~ ^[0-9]*$ ]] && delta=${delta}.0	#date command requires delta to be floating-point value
n=1 

while read -r line || [ -n "$line" ] # reads last line even if it does not end with newline
do 
   if [[ $line =~ "-->" ]] 
   then 
	  if [[ $n > $skip ]] 
	  then 
		 ft=${line%% *}
		 st=${line##* }
		 echo "$(date -d"$ft +$delta sec" +"%T,%N") --> $(date -d"$st +$delta sec" +"%T,%N")"
	   else 
		 echo "$line" 
	  fi 
	  n=$((n+1)) 
   else 
	  echo "$line" 
   fi 
done < "$srtfile"
Previous example with delta=2.2 and skip=0 results in

Code: Select all

1
00:02:19,640000000 --> 00:02:22,575000000
Senator, we're making
our final approach into Coruscant.

2
00:02:22,676000000 --> 00:02:24,701000000
Very good, Lieutenant.
I'm not sure if the trailing zeros created by %N cause problems. If so we may trim them.

User avatar
puppy_apprentice
Posts: 299
Joined: Tue 07 Feb 2012, 20:32

#5 Post by puppy_apprentice »

I didn't test it on my TV or any Linux or Windows player, but i think that milli/nano seconds should be rounded to three places after the comma to be consistent with specification.

User avatar
Flash
Official Dog Handler
Posts: 13071
Joined: Wed 04 May 2005, 16:04
Location: Arizona USA

#6 Post by Flash »

A nanosecond seems like overkill. Synchronized to within a millisecond will be sufficient for human ears.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#7 Post by MochiMoppel »

Flash wrote:A nanosecond seems like overkill. Synchronized to within a millisecond will be sufficient for human ears.
Human ears are not involved when it comes to subtitles. IMO even milliseconds are overkill and one digit should be sufficient. The date command displays fractions of a second always with 9 digits and there is no straightforward way to limit this number. Question is if the program processing the time value simply ignores excess zeros.

User avatar
Flash
Official Dog Handler
Posts: 13071
Joined: Wed 04 May 2005, 16:04
Location: Arizona USA

#8 Post by Flash »

My mistake. :)

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#9 Post by MochiMoppel »

puppy_apprentice wrote:I didn't test it on my TV or any Linux or Windows player, but i think that milli/nano seconds should be rounded to three places after the comma to be consistent with specification.
Yes, rereading the spec it appears that exactly 3 digits are required.

Cutting instead of rounding should do:

Code: Select all

		 ft=${line%% *}
		 ft_new=$(date -d"$ft +$delta sec" +"%T,%N")
		 ft_new=${ft_new::12}	#cut to milliseconds
		 st=${line##* }
		 st_new=$(date -d"$st +$delta sec" +"%T,%N")
		 st_new=${st_new::12}	#cut to milliseconds
		 echo "$ft_new --> $st_new"

User avatar
misko_2083
Posts: 114
Joined: Tue 08 Nov 2016, 13:42

#10 Post by misko_2083 »

MochiMoppel wrote:
puppy_apprentice wrote:I didn't test it on my TV or any Linux or Windows player, but i think that milli/nano seconds should be rounded to three places after the comma to be consistent with specification.
Yes, rereading the spec it appears that exactly 3 digits are required.

Cutting instead of rounding should do:

Code: Select all

		 ft=${line%% *}
		 ft_new=$(date -d"$ft +$delta sec" +"%T,%N")
		 ft_new=${ft_new::12}	#cut to milliseconds
		 st=${line##* }
		 st_new=$(date -d"$st +$delta sec" +"%T,%N")
		 st_new=${st_new::12}	#cut to milliseconds
		 echo "$ft_new --> $st_new"
Or next

Code: Select all

date -d"$ft +$delta sec" +"%T,%3N" 
date +"%T.%3N" --> returns the current time with nanoseconds rounded to the first 3 digits, which is milliseconds.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#11 Post by MochiMoppel »

misko_2083 wrote:date +"%T.%3N" --> returns the current time with nanoseconds rounded to the first 3 digits, which is milliseconds.
Great, thanks!
I've never seen this documented.

User avatar
puppy_apprentice
Posts: 299
Joined: Tue 07 Feb 2012, 20:32

#12 Post by puppy_apprentice »

So the final version is:

Code: Select all

#!/bin/sh
# srted.sh by puppy_apprentice, MochiMoppel, Flash and misko_2083
# simple script to adjust times for subtitles in SRT format
# https://matroska.org/technical/specs/subtitles/srt.html
# usage: srted.sh srtfile delta skip

srtfile=$1 # file with subtitles in SRT format
delta=$2   # number of seconds and/or miliseconds, format: S, 0.M, S.M
skip=$3    # start processing after subtitle number

[[ $delta =~ ^[0-9]*$ ]] && delta=${delta}.0   #date command requires delta to be floating-point value
n=1

while read -r line || [ -n "$line" ] # reads last line even if it does not end with newline
do
   if [[ $line =~ "-->" ]]
   then
     if [[ $n > $skip ]]
     then
       ft=${line%% *}
       st=${line##* }
       echo "$(date -d"$ft +$delta sec" +"%T,%3N") --> $(date -d"$st +$delta sec" +"%T,%3N")"
      else
       echo "$line"
     fi
     n=$((n+1))
   else
     echo "$line"
   fi
done < "$srtfile"
BTW Is it is possible to attach to GtkDialog window a video preview widget to make a visual subtitles maker?

User avatar
Flash
Official Dog Handler
Posts: 13071
Joined: Wed 04 May 2005, 16:04
Location: Arizona USA

#13 Post by Flash »

puppy_apprentice wrote: Is it is possible to attach to GtkDialog window a video preview widget to make a visual subtitles maker?
Please start a new thread for this question. Otherwise, no one will ever see it. Thanks. :)

Post Reply