El siguiente programa tiene por finalidad modificar el tiempo
de los subtítulos de un archivo SRT. Todo comenzó porque
quería tener el episodio 9 de Cowboy Bebop con
audio en japonés y subtítulos en español
y el archivo de subtítulos que me bajé de internet estaba
desfasado por 89 segundos (era de la versión completa
con intro). Cuando abrí el archivo SRT, me di cuenta de
que podía ser editado fácilmente
pues era un simple archivo de texto.
Seguro que deben haber miles de programas que hagan lo mismo,
pero como no hay nada mejor que un problema simple para familiarizarse
con un nuevo entorno pensé programarlo todo usando el Dev-C++.
En la parte de depuración extrañé algunas
cosas que el VC++ tiene (edit & continue por ejemplo)
pero tiene otras ventajas como ser gratuito, de código
abierto y usar el MinGW (g++) que está mucho mas cerca
del estándar ANSI que el VC++.
El código no tiene nada del otro mundo:
|
//=============================================================================
// Este programa modifica los tiempos de subtítulos para archivos SRT
// This program modifies the timing of SRT files.
//-----------------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
bool ConvertToSeconds (string strTime, float & secs)
{
// convierte cadena de la forma "h:mm:ss.ss" en segundos
char strTmp[11];
strncpy (strTmp, strTime.c_str (), 10);
strTmp[1] = 0;
strTmp[4] = 0;
strTmp[10] = 0;
int h = atoi (strTmp);
int m = atoi (strTmp + 2);
float s = atof (strTmp + 5);
if ((h < 0) || (h > 9) || (m < 0) || (m > 59) || (s < 0) || (s >= 60))
{
return false;
}
secs = s + (60 * m) + (3600 * h);
return true;
}
bool ConvertToStr (float secs, string & strTime)
{
// convierte tiempo en segundos en cadena de la forma "h:mm:ss.ss"
if ((secs < 0) || (secs >= 36000))
{
return false;
}
int h = int (secs) / 3600;
secs = secs - (3600 * h);
int m = int (secs) / 60;
float s = secs - (60 * m);
char strTmp[11];
// %05.2f: formato que llena de ceros los 5 caracteres disponibles
// mostrando 2 digitos decimales siempre.
snprintf (strTmp, 10, "%d:%02d:%05.2f", h, m, s);
strTmp[10] = 0;
strTime.assign (strTmp);
return true;
}
int exit_err (string strExit)
{
cerr << strExit << endl;
system ("PAUSE");
return EXIT_FAILURE;
}
int main (int argc, char *argv[])
{
//-----------------------------------------------------------
// Cadena de comando
//-----------------------------------------------------------
string strArgs ("subtitle.exe \"input.srt\" \"inc_secs\" \"output.srt\"");
if (argc != 4)
{
return exit_err ("Usage: " + strArgs);
}
string strFileInput (argv[1]);
string strFileOutput (argv[3]);
double secsToIncrement = atof (argv[2]);
if (!secsToIncrement)
{
return exit_err ("inc_secs must be NON ZERO");
}
//-----------------------------------------------------------
// Cadena a transformar de la forma
//-----------------------------------------------------------
//Dialogue: Marked=0,0:01:29.99,0:01:34.03,Default,NTP,0000,0000,0000,!Effect,Aqu�... no hay nadie
//-----------------------------------------------------------
// Sumarle el tiempo en segundos [secsToIncrement]:
//-----------------------------------------------------------
//Dialogue: Marked=0,0:01:29.99+secsToIncrement,0:01:34.03+secsToIncrement,Default,NTP,...
// abrir archivos
ifstream fileInput (strFileInput.c_str ());
if (! fileInput)
{
return exit_err ("Error opening file: " + strFileInput);
}
ofstream fileOutput (strFileOutput.c_str ());
if (! fileOutput)
{
return exit_err ("Error creating file: " + strFileOutput);
}
string minString ("Dialogue: Marked=0,");
string::size_type minLen = minString.size ();
string::size_type posIni;
string strLine; // para leer lineas del archivo
string strIni; // tiempo inicial
string strEnd; // tiempo final
float secsIni;
float secsEnd;
while (getline (fileInput, strLine))
{
if (strLine.size () > minLen)
{
posIni = strLine.find ("Dialogue: Marked=0,");
if (posIni != string::npos)
{
// cadena de la forma: "0:01:29.99,0:01:34.03"
strIni = strLine.substr (posIni + minLen, 10);
strEnd = strLine.substr (posIni + minLen + 11, 10);
if (ConvertToSeconds (strIni, secsIni))
{
if (ConvertToSeconds (strEnd, secsEnd))
{
// agregar el tiempo indicado
secsIni += secsToIncrement;
secsEnd += secsToIncrement;
if (ConvertToStr (secsIni, strIni))
{
if (ConvertToStr (secsEnd, strEnd))
{
fileOutput << strLine.substr (0, posIni) << minString
<< strIni << "," << strEnd
<< strLine.substr (minLen + 21) << endl;
continue;
}
}
}
}
return exit_err ("ERROR: " + strLine);
}
}
fileOutput << strLine << endl;
}
// archivos destruido automaticamente al salir de main()
system ("PAUSE");
return EXIT_SUCCESS;
}
|
El proyecto completo esta aquí subtitles.zip y
si sólo quieres
el ejecutable esta aquí: subtitle_exe.zip.
[NOTA] Para usar el programa debes poner el archivo SRT que
quieres modificar en el mismo directorio del programa y pasarle
como parámetros el nombre del archivo a modificar, el tiempo
en segundos a sumar (puede ser negativo) y el nombre del nuevo
archivo SRT a crear, todo esto desde la consola del sistema (Menú
de inicio -> Ejecutar -> cmd):
subtitle.exe bebop.srt -89 new_bebop.srt
|