Table of Contents

Synchroniser la piste de sous-titres

Obtenir le décalage

2 méthodes pour obtenir le décalage :

Empirique

Jouer avec la synchronisation de piste sous vlc.

Chiffrée

Recueillir le minutage précis de la première phrase (voire de la dernière) et la comparer au timestamp du sous-titre correspondant.

Script

ToDo

subsync.py
#!/usr/bin/python
# -*- encoding:utf-8 -*-
 
"""Syncs SubRip subtitle files."""
 
# Author : Ginko
# Date : 29/06/2014
# Version : 0.1.b
# Licence : CC-By
 
# SubRip example
"""1
00:00:20,672 --> 00:00:24,972
Entre l’Australia et la South America,
dans l’Océan South Pacific…"""
 
import re, sys
 
class formatException(BaseException):
     pass
 
class SrTime(object):
	"""SubRip Time. Can be negative."""
	timePat = re.compile(r'(\d{2})\:(\d{2})\:(\d{2}),(\d{3})')
	def __init__(self, raw=None, sign='+'):
		self.sign = sign
		if raw == None:
			self.h, self.m, self.s, self.ms = (0,0,0,0)
		elif type(raw) == str:
			if raw[0] == '-':
				self.sign = '-'
				raw = raw[1:]
			self.h, self.m, self.s, self.ms = self.parse(raw)
		elif type(raw) in (list, tuple):
			self.h, self.m, self.s, self.ms = raw
		else:
			self.h, self.m, self.s, self.ms = (0,0,0,0)
	def parse(self, raw):
		"""Parse da time. SubRip Format"""
		m = SrTime.timePat.match(raw)
		if m:
			return map(int, (m.group(1), m.group(2), m.group(3), m.group(4)))
		else:
			raise formatException(raw)
	def __add__(self, delay):
		if delay.sign == '-': return self - delay
		if self.sign == '-': return delay - self
		result = SrTime()
		s, result.ms = divmod(self.ms + delay.ms, 1000)
		m, result.s = divmod(self.s + delay.s + s, 60)
		h, result.m = divmod(self.m + delay.m + m, 60)
		result.h += h + delay.h
		return result
	def __sub__(self, delay):
		result = SrTime()
		s, result.ms = divmod(self.ms - delay.ms, 1000)
		m, result.s = divmod(self.s - delay.s + s, 60)
		h, result.m = divmod(self.m - delay.m + m, 60)
		result.h += h - delay.h
		if result.h < 0 : result = SrTime() # I could have used the negative sign to respect arithmetics but in subtitle, a negative timestamp is dumb
		return result
	def __str__(self):
		"""Print da time. SubRip Format."""
		return "{:02}:{:02}:{:02},{:03}".format(self.h, self.m, self.s, self.ms)
	def __repr__(self):
		return(str(self))
 
if __name__ == "__main__":
 
	def printHelp():
		print("Usage: subsync.py <file name> <SubRip Formatted Time>.")
		print('Time can be negative. Ex.: "-00:02:15,042"')
		sys.exit(0)
 
	def main(fileName, delay):
		"""Read srt file and write a "delayed" file."""
		pat = re.compile(r'\-?\d{2}\:\d{2}\:\d{2},\d{3}')
		def delayIt(rawTime):
			return str(SrTime(rawTime.group(0)) + delay)
		with open(fileName, 'r') as infile:
			with open("{}.delayed.srt".format(fileName.rstrip('.srt')), 'w') as outfile:
				for i, line in enumerate(infile):
					try:
						outfile.write(pat.sub(delayIt, line))
					except formatException:
						print("Bad time format at line {}".format(i)) # I think it cannot happen... just looks cleaner
						print("Aborting process.")
						sys.exit(1)
 
 
	if sys.argv[1] in ('-h', '--help'):
		printHelp()
 
	try:
		fileName, delay = sys.argv[1:3]
	except ValueError:
		print("Some arg missing.\n")
		printHelp()
 
	try: 
		delay = SrTime(delay)
	except formatException:
		print("Bad time format.\n")
		printHelp()
 
	try:
		main(fileName, delay)
	except IOError:
		print("Can't read or write files.\n")
		printHelp()