Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
For most of the people here, this will be basic stuff. But I'm still learning, so bear with me .
I have a SRT file (subtitles) and it doesn't match with the movie. The subs are 3 seconds too late, so I will need to add 3 seconds to start and end timestamp.
So now I get the seconds and I will need to add 3 to it.
First question, how can I do that easily?
Second question, how can I manage the minutes, because when I need to add 3 seconds to 58, I will also need to incerment the minutes...
Or do you guys have a better way?
Thanks in advance!
Are you encoding the subtitles into the movie, or just using them during playback? Either way, there is usually a way to set the delay through the player during playback.
I'm not burning them on the video file (maybe not yet)
But indeed it's a good point you're making, but then again it might be a good practice to get me starting
I believe you are missing the point here...
I am aware of there being programs capable of doing this without any efforts, but I want to do it myself and creating a script for it... (like I said before).
Instead of giving me links of programs, I ask for your help for this script.
I do appreciate the links and ready-solutions...
Better to pass incr as a command line argument using awk's -v option and error trap it is not greater than 59 or better still modify the code to handle > 59 seconds.
EDIT: and, of course, add handling of the second time string.
Since the %H:%M:%S,%N is a standard format accepted by the date command, you can a script like this:
Code:
#!/bin/bash
#
delay="3 seconds"
while read start s end
do
if [[ $start =~ ^..:..:..,... ]]
then
start=$(date -d "$start $delay" +%H:%M:%S,%N)
end=$(date -d "$end $delay" +%H:%M:%S,%N)
echo ${start:0:12} $s ${end:0:12}
else
echo $start $s $end
fi
done < file.srt
%N is the format for nanoseconds that you can easily truncate to milliseconds using the shell variable expansion to extract substrings. Anyway, this is slower than the awk code suggested by catkin, since it makes use of a great number of time functions calls.
Since the %H:%M:%S,%N is a standard format accepted by the date command, you can a script like this:
Code:
#!/bin/bash
#
delay="3 seconds"
while read start s end
do
if [[ $start =~ ^..:..:..,... ]]
then
start=$(date -d "$start $delay" +%H:%M:%S,%N)
end=$(date -d "$end $delay" +%H:%M:%S,%N)
echo ${start:0:12} $s ${end:0:12}
else
echo $start $s $end
fi
done < file.srt
%N is the format for nanoseconds that you can easily truncate to milliseconds using the shell variable expansion to extract substrings. Anyway, this is slower than the awk code suggested by catkin, since it makes use of a great number of time functions calls.
First few questions:
1. the while line, what does it do? how does the command now what to read?
2. What does =~ do?
Be aware, I'm kinda new to all of this..
So be patient haha
First few questions:
1. the while line, what does it do? how does the command now what to read?
2. What does =~ do?
Be aware, I'm kinda new to all of this..
So be patient haha
Don't worry -- we were all new to this once
The while ... done command loops while the command after while returns true.
The read command reads from stdin until there are no more lines to read. Each time there is a line to read it returns true (0). When stdin runs out it returns false (non-zero).
stdin is supplied to the while loop (and hence to the read command) by the input redirect from file "file.srt" on the end of the while loop, done < file.srt
So the read command is reading from file.srt line by line. It breaks the input at spaces and/or tabs. The first "word" is assigned to variable start, the second to variable s (presumably s for string) and all the rest to variable end.
=~ is the regular expression comparison operator. Details here in the [[...]] section (but the man 7 regex page is more helpful than the man 3 regex page cited).
nice!
Indeed, I've been doing some scripting with this.
Step by step, to get the feeling with it and to see what it does.
But one thing seems to be failing (when I use the script).
Code:
echo ${start:0:12} $s ${end:0:12}
I get the following result (example)
Code:
01:+53:+02,+ --> 01:+54:+02,+
The times doesn't matter here, but I mean the format.
How do I get rid of the '+' and how do I get my nanoseconds back ?
Is this some advanced scripting with echo?
Where can I find the explanation of this?
EDIT
I increased the value of the echo from 12 to 15. So I have the nanoseconds back.
That is one question solved
1. the while line, what does it do? how does the command know what to read?
It doesn't know. Since you're interested in lines that have 3 fields separated by space, it assigns each of them to the three variables, start, s and end respectively. If a line has less than three fields a null string is assigned to the last variable(s). If a line has more than three fields, the extra fields are assigned to the last variable all together. In any case the line is printed out as it is (provided it was originally separated by blank spaces).
Quote:
Originally Posted by dragonix
2. What does =~ do?
It is the regular expression match operator. The string at the right-hand side of the operator is interpreted as a regular expression. The condition is true if the string at the left-hand side matches the regular expression. Basically it selects only those line that contain a time specification in the format of the SRT files. It should select the desired lines in the 99.99% of the cases, since doubtfully a subtitle contains a string in that format.
Therefore, the time delay is applied to the start and ending time only for the related lines, whereas the other ones are printed untouched. You can easily verify the result using diff between the original file and the newly created one.
Edit: sorry, I didn't see previous replies before posting!
1. the while line, what does it do? how does the command know what to read?
It doesn't know. Since you're interested in lines that have 3 fields separated by space, it assigns each of them to the three variables, start, s and end respectively. If a line has less than three fields a null string is assigned to the last variable(s). If a line has more than three fields, the extra fields are assigned to the last variable all together. In any case the line is printed out as it is (provided it was originally separated by blank spaces).
Quote:
Originally Posted by dragonix
2. What does =~ do?
It is the regular expression match operator. The string at the right-hand side of the operator is interpreted as a regular expression. The condition is true if the string at the left-hand side matches the regular expression. Basically it selects only those line that contain a time specification in the format of the SRT files. It should select the desired lines in the 99.99% of the cases, since doubtfully a subtitle contains a string in that format.
Therefore, the time delay is applied to the start and ending time only for the related lines, whereas the other ones are printed untouched. You can easily verify the result using diff between the original file and the newly created one.
Edit: sorry, I didn't see previous replies before posting!
And also, everybody explains in a different way. So it's nice to have different approaches to the same problem!
Thanks
EDIT
In the meantime, I found this about the echo command
Quote:
Another expansion that exists is to extract substrings from the expanded value using the form ${VARffset:length}. This works in the expected form: offsets start at zero, if you don't specify a length it goes to the end of the string. For example:
str=abcdefgh
echo ${str:0:1}
echo ${str:1}
outputs "a" and "bcdefgh".
So that makes sense now, but now I need to get rid of the '+'...
EDIT 2
I did it like this (atm)
Code:
#!/bin/bash
#
delay="3 seconds"
while read start s end
do
if [[ $start =~ ^..:..:..,... ]]
then
start=$(date -d "$start $delay" +%H:%M:%S,%N)
end=$(date -d "$end $delay" +%H:%M:%S,%N)
echo ${start:0:15} $s ${end:0:15} | tr -d '+'
else
echo $start $s $end
fi
done < file.srt
Is that a proper solution? Or is there an easier or better way to do this?
And how do I decrease the seconds with 3 ? (made a mistake, instead of adding I should be decreasing it )
EDIT 3
W00t!!
I guess I found it
Code:
#!/bin/bash
#
delay="3 seconds ago"
while read start s end
do
if [[ $start =~ ^..:..:..,... ]]
then
start=$(date -d "$start $delay" +%H:%M:%S,%N)
end=$(date -d "$end $delay" +%H:%M:%S,%N)
echo ${start:0:15} $s ${end:0:15} | tr -d '+'
else
echo $start $s $end
fi
done < file.srt
------------------------------------- Final Edit
This is my final code for the script. And it works
Happy me!!!
I ran it like
Code:
# ./script.sh > file_edit.srt
Code:
#!/bin/bash
#
# To decrease the amount of time by 3 seconds
#
# Changing the values
delay="3 seconds ago"
while read start s end
do
if [[ $start =~ ^..:..:..,... ]]
then
start=$(date -d "$start $delay" +%H:+%M:+%S,+%N)
end=$(date -d "$end $delay" +%H:+%M:+%S,+%N)
echo ${start:0:15} $s ${end:0:15} | tr -d '+'
else
echo $start $s $end
fi
done < file.srt
If there are any improvements possible, let me know!!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.