0

I have a user-defined function (return_times) that takes json file and returns two datetime-like strings.

time_1, time_2= return_times("file.json")
print(time_1, time_2) # outputs: 00:00:11.352 00:01:51.936

By datetime-like string I mean 00:00:11.352 which suits '%H:%M:%S.%f' formatting. However, when I try to convert them into milliseconds, I get negative values.

from datetime import datetime

dt_obj_1 = datetime.strptime(time_1, '%H:%M:%S.%f')
start_ms = dt_obj_1.timestamp() * 1000

dt_obj_2 = datetime.strptime(time_2, '%H:%M:%S.%f')
end_ms = dt_obj_2.timestamp() * 1000

print(start_ms, end_ms ) # outputs: -2209019260648.0 -2209019160064.0

If I success I would like to trim a video with the following command:

from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
ffmpeg_extract_subclip("long_video.mp4", start_ms, end_ms, targetname="video_trimmed.mp4"), so just delete ` * 1000` part. 

Note that ffmpeg_extract_subclip requires its t1 and t2 parameters to be in seconds, not in milliseconds as I initially thought.

Because of those negative integers I am not able to successfully run the trimming process. I searched the web that mainly discusses several formats for the year, month and day, but not '%H:%M:%S.%f'.

What may I be overlooking?

bit_scientist
  • 1,496
  • 2
  • 15
  • 34

4 Answers4

1

What may I be overlooking?

time.strptime docs

The default values used to fill in any missing data when more accurate values cannot be inferred are (1900, 1, 1, 0, 0, 0, 0, 1, -1).

whilst start of epoch is 1970. You might get what you want by computing delta between what you parsed and default strptime as follows:

import datetime
time1 = "00:00:11.352"
delta = datetime.datetime.strptime(time1, "%H:%M:%S.%f") - datetime.datetime.strptime("", "")
time_s = delta.total_seconds()
print(time_s)

output

11.352
Daweo
  • 31,313
  • 3
  • 12
  • 25
  • this answered my main question which solves the value returning a value in milliseconds. Do note that, `ffmpeg_extract_subclip` requires `t1` and `t2` to be in seconds in milliseconds (as I initially thought). @Daweo, edit your answer so that is time_ms in seconds not ms. I will do the same with my question. – bit_scientist Oct 27 '21 at 08:09
  • 1
    @bit_scientist I edited my answer, note that whilst `ffpmeg_extract_subclip` require float, if you use `ffmpeg` directly (from command line) you might use `00:00:11.352` as-is, see for example following tutorial https://ottverse.com/trim-cut-video-using-start-endtime-reencoding-ffmpeg/ – Daweo Oct 27 '21 at 08:58
0

You need to add the year date (year, month, day) to datetime, else this will default to 1 January 1900.

What you do is this:

from datetime import datetime
s = "00:00:11.352" 
f = '%H:%M:%S.%f'
datetime.strptime(s, f) # datetime.datetime(1900, 1, 1, 0, 0, 11, 352000)

One way to do this is to append the date-string to the time-string you receive from return_times

Felix
  • 332
  • 1
  • 9
0

From https://stackoverflow.com/a/59200108/2681662

The year 1900 was before the beginning of the UNIX epoch, which was in 1970, so the number of seconds returned by timestamp must be negative.

What to do?

It's better to use a time object instead of a datetime object.

from datetime import time

time_1 = "00:00:11.352"
hours, minutes, seconds = time_1.split(":")

print(time(hour=int(hours), minute=int(minutes), second=int(float(seconds)),
           microsecond=int(float(seconds) % 1 * 1000000)))
MSH
  • 1,743
  • 2
  • 14
  • 22
  • since the OP wants total (milli)seconds, I don't think you need a `time` object at all. Also, if you map the "seconds" part to a float, fractional seconds are already included. – FObersteiner Oct 27 '21 at 08:07
  • I actually tried to map the seconds to `float`. However the `time` object expect the value as an `int`. `TypeError: integer argument expected, got float` – MSH Oct 27 '21 at 08:14
  • The reason I thought a `time` object would be better is, in an extreme condition the `datetime` delta object may have leap second. – MSH Oct 27 '21 at 08:17
  • the point is, the input represents a duration, not a time of day. So time or datetime are inappropriate data structures in my opinion. Concerning leap seconds, see also [docs](https://docs.python.org/3/library/datetime.html#technical-detail), technical note #4. – FObersteiner Oct 27 '21 at 08:27
-1

You can split the time string into hours, minutes, seconds and miliseconds and with some simple math calculations, you get the whole time in miliseconds

  • Actually this is a good approach (e.g. `sum(a*b for a, b in zip(map(float, "00:00:11.352".split(':')), (3600, 60, 1)))`. However, you should add an example to make this a helpful answer. Otherwise, this should be a comment. – FObersteiner Oct 27 '21 at 08:33
  • Sorry but I'm a newbie in stackoverflow and dont have reputation needed to add comment. thanks for the advice – saeedhosseini Oct 27 '21 at 09:15
  • commenting takes 40 rep I think, so it shouldn't take you too long to get there. you can also edit your answer to improve it. – FObersteiner Oct 27 '21 at 09:23