banner


Modificando el tiempo de subtítulos (Dev-C++)


 

Lo que me gusta del Dev-C++ es que es pequeño, fácil de instalar y con un poco de configuración bastante simple de usar. Últimamente lo uso para programas simples y rápidos en C++ porque tiene un mejor soporte de STL del que viene con VC++ 6. Además de esta manera puedo verificar que mi código no usa funciones NO ANSI a las que te acostumbras cuando programas en VC++.

 

 

 

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:

 

subtitle.cpp



//=============================================================================
// 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

 

 

 

 


Diseño y coordinación : Esaú Rodriguez Oscanoa - Lima - Per�

Esta página se ve mejor en Mozilla Firefox a 1024x768


Hosted by www.Geocities.ws

1