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í:
- Primero detectamos las lineas de tiempo con if(strpos($cadena,":",0)==2)
- capturamos el tiempo de inicio con substr($cadena,0,12);.
- capturamos el tiempo final con substr($cadena,strpos($cadena,":",12)-2,12);.
- Pasamos a segundos la hora inicial y la multiplicamos por k: horatoseg($hinicio)*$k;.
- La hora corregida la volvemos al formato HH:MM:SS,ddd con segtohora($hinicorrseg);.
- 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>