CORREGIR LOS TIEMPOS DE UN ARCHIVO .srt DESINCRONIZADO CON PHP
Aquí aplicamos todo lo visto en Manejo de archivo de texto (R/W) y las funciones de hora.
Sea tp el tiempo del último diálogo de la película y ts la de los subtítulos entonces dif=tp-tses el desfasaje máximo (al final de la peli).
Sean tn (t sub n) los tiempos sucesivos de los subtítulos, entonces el offset correspondiente a cada uno será:
offset sub n= dif . tn/ts
Ahora t'n (nuevo tiempo offseteado) es t'n= tn + offset o sea t'n = tn + (dif . tn/ts)
Reemplazando dif por su valor queda t'n = tn + tn.(tp-ts)/ts.    Saco factor común tn.
Esto me da t'n = tn.(1 + tp-ts)/ts ahora distribuyo el denominador ts.
Queda t'n = tn.( 1 + tp/ts-ts/ts) o sea t'n = tn.tp/ts es decir t'n = K.tn con K=tp/ts
Solo hay que abrir el .srt, leerlo linea a linea y:
  • En aquellas que comienzan con dos numeros y : se parsean los 2 horarios HH:MM:SS,sss, se transforman en segundos, se le multiplica por K y se las reescribe como HH:MM:SS,sss.
  • Las otras lineas se reescriben sin cambiar. Y listo.
Algunos detalles importantes:

DE LA CARGA DEL ARCHIVO

El form con enctype="multipart/form-data" sirve para subir archivos, el input debe llevar type="file" accept=".srt" el accept sirve para que solo permita esa extensión su name="archivo" deja que capturemos por javascript el onchange que dispara el AJAX. El id="formulario" del FORM nos permite en el AJAX pasar todos los datos al script con var formData = new FormData($("#formulario")[0]);.
En el AJAX el success solo chequea si retorna Exito con if(datos.indexOf('Exito') == 0) si es así en la div msg ponemos que subió, si no el mensaje de error del script PHP que viene en data, en ambos casos ocultamos el gif esperando. En el script PHP con $_FILES["archivo"] capturo en forma de array toda la info del archivo subido (ver código). Cuando el archivo sube va a un temporario del cual al subir el siguieente se borra por eso hay que moverlo a un sitio definitivo, con un nombre. Esto lo realiza move_uploaded_file($ruta_provisional, $final) La ruta provisional viene en el array _FILES como "tmp_name".

DE LA RESINCRONIZACIÓN DEL ARCHIVO

Las funciones de parseo y conversión de tiempos están explicadas en "Manejo de tiempos SQL y otros" VER solo segtohora() tiene una modificación para tomar 3 decimales. (Necesario por el protocolo que usa .srt).
En //preproceso comenzamos por determinar k usando las funciones ya vistas, y la guardamos en $k y mostramos los valores para control con echo $msj;.
En if($k!=0){ comenzamos la corrección. (Una vez completa se baja el corregido como .txt con <a href="media/corregido.txt" download>). Como sabemos que en un .srt los tiempos SIEMPRE son de la forma fija HH:MM:SS,ddd --> HH:MM:SS,ddd podemos parsearlos así:
  1. Primero detectamos las lineas de tiempo con if(strpos($cadena,":",0)==2)
  2. capturamos el tiempo de inicio con substr($cadena,0,12);.
  3. capturamos el tiempo final con substr($cadena,strpos($cadena,":",12)-2,12);.
  4. Pasamos a segundos la hora inicial y la multiplicamos por k: horatoseg($hinicio)*$k;.
  5. La hora corregida la volvemos al formato HH:MM:SS,ddd con segtohora($hinicorrseg);.
  6. repetimos el proceso para la hora final
Finalmente grabo el archivo corregido, explicado en Manejo de archivos de texto VER.
Las lineas nuevas ( solo números, --> y ":" )agregan un fin de linea "\n" porque son strings "de novo" (y todos sus caracteres son estandar o sea se leen igual en todas las codificaciones).
Las lineas de texto, las lineas en blanco y la numeración, se copian y graban sin cambiarlas, por eso no se les agrega un fin de linea, ya lo llevan en el original. El detalle es que la página está codificada en UTF-8 pero el .srt en ISO-8859-x por eso debemos convertirla a UTF-8 con mb_convert_encoding($cadena, "UTF-8","ISO-8859-1,ISO-8859-5,ISO-8859-8"); antes de hacerle un echo() en la página.

VER EL ARCHIVO

También acá hay que aplicar el cambio de codificación para poder ver bien los textos del archivo .srt original.
						
1) Código HTML necesario para subir el archivo (junto al código javascript)

<div style="text-align:left;">
	<div style="text-align:center;font-size:14px;margin-bottom:15px; ">
		PASO 1° SUBIR EL .srt a RESINCRONIZAR
	</div>
	<form method="post" id="formulario" enctype="multipart/form-data">
		<div style="margin-bottom:10px; ">
			Subir el archivo de subtitulos(tamaño maximo:500K valida solo .srt ) 
		</div>
		<div> 
			1° <input name="archivo" type="file" accept=".srt" style="height:24px; ">
			<span id="esperando" style="visibility: hidden; ">
				<img src="esperando.gif" width="16" height="16" />
			</span>
		</div>
		<div style="margin-bottom:10px; margin-top:20px; text-align:center;" id="msg"> </div>
	</form>	
</div>



2) Código Javascript (Jquery)

<script>
	$(document).ready(function(){
		$("input[name='archivo']").on("change", function(){		//es la forma de indicar el FILE
			var formData = new FormData($("#formulario")[0]);	//carga todos los datos del form en array
      	 	 	var ruta = "tec-php-srt-procesar.php";				//ruta del script uploader
			$("#esperando").css("visibility", "visible");		// esperando.....
			$.ajax({
				url: ruta,
				type: "POST",
				data: formData,        //datos del form declarado
				contentType: false,
				processData: false,
				success: function(datos){
					if(datos.indexOf('Exito') == 0){
						$("#msg").html('El archivo ha subido con éxito');	//borra los mensajes anteriores
						$("#esperando").css("visibility", "hidden");		//desaparece esperando....
					}else{
						$("#esperando").css("visibility", "hidden");		//desaparece esperando....
						$("#msg").html(datos);					//envío el mensaje de error
						}
               			} //fin success	
           		}); // fin ajax
		}); // fin on change 
	}); // fin ready.			   
</script>

3) Script PHP llamado por AJAX (devuelvo solo un string con mensaje)

<?
$final = "media/original.srt";		//nombre del archivo que grabo en el disco del server
if (isset($_FILES["archivo"])){   	//si viene algo del form
	$file = $_FILES["archivo"];   	//cargo en $file la info (array)
	$nombre = $file["name"];	  	//nombre del archivo
	$tipo = $file["type"];		  	//tipo de archivo
	$ruta_provisional = $file["tmp_name"];  //ruta temporaria
 	$size = $file["size"];			//tamaño					
	if (strlen($nombre)<>0 || strlen($ruta_provisional)<>0){
		if(move_uploaded_file($ruta_provisional, $final)){		
			echo "Exito";
		}else{
			echo "El archivo no pudo moverse a la posicion final";
		}
   	}else{
		echo "No subio el archivo";
	}
}else{
		echo "No se eligió archivo";
}
?>

4) HTML y PHP para procesar el .srt


FORM

<div style="text-align:center; margin:20px; padding:5px; border: solid 1px #333 ">
	<div style="text-align:left;">
		<div style="text-align:center;font-size:14px;margin-bottom:15px; ">
			PASO 2° PROCESAR LOS ARCHIVOS
		</div>
		<form  method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
			<input name="accion" type="hidden" value="procesar" />
			<div style="margin-bottom: 10px; margin-left:10px;">
				<input name="ts" type="text" style="margin-left:5px;" value="" size="10" maxlength="20" />
				1) Abrir el .srt y anotar el tiempo final del último subtitulo (HH:MM:SS,sss)			
			</div>
			<div style="margin-bottom: 10px; margin-left:10px;">
				<input name="tp" type="text" style="margin-left:5px;" value="" size="10" maxlength="20" />
				2) Correr la peli y anotar el tiempo final del último audio (HH:MM:SS,sss).
			</div>
			<div style="margin-bottom: 10px;">
				<input type="Submit" name="Submit" value="CORREGIR SUBTITULOS" style="margin-left:10px;" />
			</div>
		</form>
	</div>
</div>

PROCESAR

<?
	function nhoras($f) {
		return substr($f,0,2);
	}
	function nminutos($f) {
		return substr($f,3,2) ;
	}
	function nsegundos($f) {
		return substr($f,6);
	}
	function horatoseg($h){
		return substr($h,0,2)*3600 + substr($h,3,2)*60 + str_replace(",",".",substr($h,6));
	}
	function segtohora($s){
		if ($s>86399){
			return NULL;
		}else{
			$r = round($s,3); 
			$h=floor((string)$r/3600);
			if (strlen($h)==1){
				$hc= "0".$h;
			}else{
				$hc= $h;
			}
			$m = floor((string)(($r - ($h * 3600)) / 60));
			if (strlen(floor((string)$m))==1){
				$mc= "0".$m;
			}else{
				$mc= $m;
			}
			$seg = $r - ($h * 3600) - ($m * 60);
			$seg = number_format($seg,3,',','');
			if ($seg<10){	
				$sc= "0".$seg;
			}else{
				$sc= $seg;
			}
			$ti = $hc.":".$mc.":".$sc;
			return $ti;
		}
	}
	if($_POST) {
			$tp=$_POST["tp"];
			$ts=$_POST["ts"];
		}
		if($_POST["accion"]=="procesar") {    //inicio if POST
			//parametros
			$srt="original.srt";
			$srtcorr="corregido.txt";
			$arch = "media/".$srt;
			$archcorr = "media/".$srtcorr;
			//preproceso
			if (horatoseg($ts)==0){
				$msj="LLENAR LAS HORAS<br>";
				$k=0;
			}else{
				$k=horatoseg($tp)/horatoseg($ts);
				$tsenseg=horatoseg($ts);
				$dif=horatoseg($tp)-$tsenseg ;
				$msj="Ultimo audio. : ".$tp." en segundos: ".horatoseg($tp). "<br>";
				$msj=$msj."Ultimo subt. : ".$ts." en segundos: ".horatoseg($ts). "<br>";
				$msj=$msj."El corrimiento es de :".$dif. "segundos<br>";
				$msj=$msj."El coeficiente k es de :".$k. "<br>";
				
			}
			?>
			<div style="text-align:left; margin:20px; padding:5px; border: solid 1px #333 ">
				<div style="margin-bottom:15px; ">
					<? echo $msj; ?>
				</div>
			</div>
			<div style="text-align:center; margin:20px; padding:5px; border: solid 1px #333 ">     
				<div style="text-align:left;">    
					<?	
					if($k!=0){ 
					?>    
						<div style="text-align:left;">
							<a href="media/corregido.txt" download>download el .srt corregido baja como .txt</a>
						</div>
					<?	 
						if($conectorcorr = fopen($archcorr, "w")){ //no puedo abrir el .txt
							if (file_exists ($arch)) {	
								if($conector = fopen($arch, "r")){   //no puedo abrir el .srt existente
									$msj= $msj." archivo ".$srt." abierto con éxito<br>";
									while(!feof($conector)){
										$cadena = fgets($conector);	
										if(strpos($cadena,":",0)==2){					
											$hinicio= substr($cadena,0,12);
											$hfin = substr($cadena,strpos($cadena,":",12)-2,12);					
											$hinicorrseg = horatoseg($hinicio)*$k;
											$hinicorr=segtohora($hinicorrseg);
											//proceso fin
											$hfincorrseg = horatoseg($hfin)*$k;
											$hfincorr=segtohora($hfincorrseg);
											echo $cadena."      ".$hinicorr." --> ".$hfincorr."<br>";
											$grabo = fwrite($conectorcorr,$hinicorr." --> ".$hfincorr."\n");   // lleva ."\n" porque es string nuevo
										}else{
											$cadenautf8 = mb_convert_encoding($cadena, "UTF-8","ISO-8859-1,ISO-8859-5,ISO-8859-8");
											echo $cadenautf8."<br>";
											//echo $cadena."<br>";
											$grabo = fwrite($conectorcorr,$cadena);  // no lleva ."\n" porque ya lo tiene cadena
										}					
									}	
									fclose($conector);
								}else{
									$msj= $msj."No se puede abrir el archivo<br> ";
								}	
							}else{
								$msj= $msj."No existe el archivo<br> ";
							}
							//del if crea archivo
							fclose($conectorcorr);
						}else{
							echo "No se puede crear el archivo corregido ";
						}
					}else{
						echo "No se puede procesar el archivo si no hay horario de pelicula y subtitulado ";
					}
					} //fin del if($_POST["accion"]=="procesar") {
				?>
			</div>      
		</div>							
						
					
© IQSystems 2023