aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/test_utils.py8
-rw-r--r--yt_dlp/downloader/common.py13
-rw-r--r--yt_dlp/extractor/adn.py9
-rw-r--r--yt_dlp/utils.py30
-rw-r--r--yt_dlp/webvtt.py8
5 files changed, 38 insertions, 30 deletions
diff --git a/test/test_utils.py b/test/test_utils.py
index 9a5e3f0f0..d84c3d3ee 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -1390,21 +1390,21 @@ The first line
</body>
</tt>'''.encode('utf-8')
srt_data = '''1
-00:00:02,080 --> 00:00:05,839
+00:00:02,080 --> 00:00:05,840
<font color="white" face="sansSerif" size="16">default style<font color="red">custom style</font></font>
2
-00:00:02,080 --> 00:00:05,839
+00:00:02,080 --> 00:00:05,840
<b><font color="cyan" face="sansSerif" size="16"><font color="lime">part 1
</font>part 2</font></b>
3
-00:00:05,839 --> 00:00:09,560
+00:00:05,840 --> 00:00:09,560
<u><font color="lime">line 3
part 3</font></u>
4
-00:00:09,560 --> 00:00:12,359
+00:00:09,560 --> 00:00:12,360
<i><u><font color="yellow"><font color="lime">inner
</font>style</font></u></i>
diff --git a/yt_dlp/downloader/common.py b/yt_dlp/downloader/common.py
index 9081794db..6cfbb6657 100644
--- a/yt_dlp/downloader/common.py
+++ b/yt_dlp/downloader/common.py
@@ -12,6 +12,7 @@ from ..utils import (
format_bytes,
shell_quote,
timeconvert,
+ timetuple_from_msec,
)
from ..minicurses import (
MultilineLogger,
@@ -75,14 +76,12 @@ class FileDownloader(object):
@staticmethod
def format_seconds(seconds):
- (mins, secs) = divmod(seconds, 60)
- (hours, mins) = divmod(mins, 60)
- if hours > 99:
+ time = timetuple_from_msec(seconds * 1000)
+ if time.hours > 99:
return '--:--:--'
- if hours == 0:
- return '%02d:%02d' % (mins, secs)
- else:
- return '%02d:%02d:%02d' % (hours, mins, secs)
+ if not time.hours:
+ return '%02d:%02d' % time[1:-1]
+ return '%02d:%02d:%02d' % time[:-1]
@staticmethod
def calc_percent(byte_counter, data_len):
diff --git a/yt_dlp/extractor/adn.py b/yt_dlp/extractor/adn.py
index a55ebbcbd..5a1283baa 100644
--- a/yt_dlp/extractor/adn.py
+++ b/yt_dlp/extractor/adn.py
@@ -15,6 +15,7 @@ from ..compat import (
compat_ord,
)
from ..utils import (
+ ass_subtitles_timecode,
bytes_to_intlist,
bytes_to_long,
ExtractorError,
@@ -68,10 +69,6 @@ class ADNIE(InfoExtractor):
'end': 4,
}
- @staticmethod
- def _ass_subtitles_timecode(seconds):
- return '%01d:%02d:%02d.%02d' % (seconds / 3600, (seconds % 3600) / 60, seconds % 60, (seconds % 1) * 100)
-
def _get_subtitles(self, sub_url, video_id):
if not sub_url:
return None
@@ -117,8 +114,8 @@ Format: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text'''
continue
alignment = self._POS_ALIGN_MAP.get(position_align, 2) + self._LINE_ALIGN_MAP.get(line_align, 0)
ssa += os.linesep + 'Dialogue: Marked=0,%s,%s,Default,,0,0,0,,%s%s' % (
- self._ass_subtitles_timecode(start),
- self._ass_subtitles_timecode(end),
+ ass_subtitles_timecode(start),
+ ass_subtitles_timecode(end),
'{\\a%d}' % alignment if alignment != 2 else '',
text.replace('\n', '\\N').replace('<i>', '{\\i1}').replace('</i>', '{\\i0}'))
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 28431ac73..b88257bc2 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -2342,14 +2342,25 @@ def decodeOption(optval):
return optval
+_timetuple = collections.namedtuple('Time', ('hours', 'minutes', 'seconds', 'milliseconds'))
+
+
+def timetuple_from_msec(msec):
+ secs, msec = divmod(msec, 1000)
+ mins, secs = divmod(secs, 60)
+ hrs, mins = divmod(mins, 60)
+ return _timetuple(hrs, mins, secs, msec)
+
+
def formatSeconds(secs, delim=':', msec=False):
- if secs > 3600:
- ret = '%d%s%02d%s%02d' % (secs // 3600, delim, (secs % 3600) // 60, delim, secs % 60)
- elif secs > 60:
- ret = '%d%s%02d' % (secs // 60, delim, secs % 60)
+ time = timetuple_from_msec(secs * 1000)
+ if time.hours:
+ ret = '%d%s%02d%s%02d' % (time.hours, delim, time.minutes, delim, time.seconds)
+ elif time.minutes:
+ ret = '%d%s%02d' % (time.minutes, delim, time.seconds)
else:
- ret = '%d' % secs
- return '%s.%03d' % (ret, secs % 1) if msec else ret
+ ret = '%d' % time.seconds
+ return '%s.%03d' % (ret, time.milliseconds) if msec else ret
def _ssl_load_windows_store_certs(ssl_context, storename):
@@ -4855,7 +4866,12 @@ def parse_dfxp_time_expr(time_expr):
def srt_subtitles_timecode(seconds):
- return '%02d:%02d:%02d,%03d' % (seconds / 3600, (seconds % 3600) / 60, seconds % 60, (seconds % 1) * 1000)
+ return '%02d:%02d:%02d,%03d' % timetuple_from_msec(seconds * 1000)
+
+
+def ass_subtitles_timecode(seconds):
+ time = timetuple_from_msec(seconds * 1000)
+ return '%01d:%02d:%02d.%02d' % (*time[:-1], time.milliseconds / 10)
def dfxp2srt(dfxp_data):
diff --git a/yt_dlp/webvtt.py b/yt_dlp/webvtt.py
index cd936e7e5..962aa57ad 100644
--- a/yt_dlp/webvtt.py
+++ b/yt_dlp/webvtt.py
@@ -13,7 +13,7 @@ in RFC 8216 ยง3.5 <https://tools.ietf.org/html/rfc8216#section-3.5>.
import re
import io
-from .utils import int_or_none
+from .utils import int_or_none, timetuple_from_msec
from .compat import (
compat_str as str,
compat_Pattern,
@@ -124,11 +124,7 @@ def _format_ts(ts):
Convert an MPEG PES timestamp into a WebVTT timestamp.
This will lose sub-millisecond precision.
"""
- msec = int((ts + 45) // 90)
- secs, msec = divmod(msec, 1000)
- mins, secs = divmod(secs, 60)
- hrs, mins = divmod(mins, 60)
- return '%02u:%02u:%02u.%03u' % (hrs, mins, secs, msec)
+ return '%02u:%02u:%02u.%03u' % timetuple_from_msec(int((ts + 45) // 90))
class Block(object):