5

long time reader first time asker.

I am working on some vtt (closed caption) files that I need to edit the timestamps for. The format of the file is as follows:

177
00:07:37.450 --> 00:07:39.690
- [Liz] How would you suggest an organization devise

178
00:07:39.690 --> 00:07:41.719
the accountabilities for culture?

179
00:07:41.719 --> 00:07:43.690
- [Tamara] It is a shared accountability  

I have written the following code to read the file, calculate the new timestamps (5% slower) and spit out the new timestamps:

from sys import argv
script, filename = argv

adjustment = input("Adjustment multiplier: ")

video = open(filename, "r+")
lines = video.readlines()

video.seek(0)

for l in lines:
    if l[:2] == "00":
        #here I've omitted a lot of calculations to turn the timestamps 
        #into milliseconds, apply the adjustment multiplier, and turn them back into
        #minutes, seconds, and milliseconds.

        new_line = str(#concatenation of new values into timestamp format)
        video.write(new_line)

video.close()

The calculations work great, but the problem is that it dumps all the new lines into the start of the file instead of writing over each timestamp line and skipping the rest.

I would love to hear what you guys think! I've been wrestling with this for a while and have tried a bunch of things but haven't quite been able to make it work.

Thank you!

  • 3
    Instead of writing over the same file, write to a separate file and then rename it if necessary. Writing to the same file risks failing mid-way and then having a file that has been partially updated. – Hosam Aly May 15 '18 at 14:16
  • 3
    In addition the line interface of text files does not allow to position the file pointer at beginning of lines: the file is read in chunks in a large buffer and lines are extracted from that buffer, but the file pointer is after the current *chunk*, possibly far beyond current line. – Serge Ballesta May 15 '18 at 14:19
  • Read the contents of the file into memory, close the file, make all modifications into the data in memory, create a new file with the modified data (with the same name of the old file if you want to override it). – Gabriel May 15 '18 at 14:20
  • 2
    https://github.com/drm/srtfix.py :) – Jean-François Fabre May 15 '18 at 14:23
  • If you're really into editing files in-place, check [**this answer**](https://stackoverflow.com/a/49734119/7553525). That being said, I do not recommend it - writing to a temporary file is much safer and considerably faster option. – zwer May 15 '18 at 14:24
  • 1
    srtfix I just mentionned does exactly what you want already (I've written such a tool myself, damn 23.976 framerates...) – Jean-François Fabre May 15 '18 at 14:34
  • @Jean-FrançoisFabre Thanks for sharing that! Looks awesome. Would this allow me to slow down the closed captions by a certain percentage? Would I simply take the framerate of my videos and apply a slower framerate to the captions using your tool? – Will Howard May 15 '18 at 14:39
  • It just adjusts the framerate. You have the source code so it's much easier to modify a working program that almost does what you want (my own tool doesn't do it either) – Jean-François Fabre May 15 '18 at 15:30

2 Answers2

1

You can try enumerate while iterating the lines, and then do the same process:

# Reading code here ...

for index, line in enumerate(lines):
    if index % 4 == 0:
        # Your code here ...

Hopefully it helps :)

Ersel Er
  • 731
  • 6
  • 22
  • Thanks for your response! Unfortunately this is just a different way to do the same thing and my problem of all of the new lines appearing at the start of the file instead of in the proper place is not solved. – Will Howard May 15 '18 at 14:32
  • Oh I understand, maybe readlines() function causes the problem. Have you tried reading [lines one by one](https://stackoverflow.com/a/3277512/4681316). Then you could do the operations on the line and write it down to another file. Or you should use regex to find the correct pattern. – Ersel Er May 15 '18 at 14:41
1

Fixed it!

All I had to do was add:

else:
        video.write(l)

to the if-statement. That way, if it matches my parameters the calculations are run and it writes the new line, but if it doesn't, it just writes the old line.

Thanks all!

  • 1
    I fixed it too :) but u are faster :) – Ersel Er May 15 '18 at 15:09
  • @ErselEr Cool, did you fix it the same way as me or a different way? – Will Howard May 15 '18 at 15:18
  • In my solution, I have iterated over the `lines` and changed the `lines[i]`(i is the index of the list lines) when it starts with time stamp. After that, outside of the for loop, I have did `video.write(lines)` instead of `video.write(l)`. – Ersel Er May 15 '18 at 16:54