본문 바로가기
C 언어

Json 파일을 자막 파일인 srt로 변경

by treeCoder 2021. 1. 2.

Json 파일을 자막 파일인 srt로 변경하는 프로그램이다.

 

구체적으로 설명하면, 아래는 음성을 텍스트로 변화하는 Speechmatics에서제공하는 Json 파일의 일부이다.

 

굵은 폰트가 자막와 그 자막이 나오는 시간이다.

 

{

      "duration": "0.09",

      "confidence": "0.960",

      "name": "the",

      "time": "12.93"

    },

    {

      "duration": "0.24",

      "confidence": "0.910",

      "name": "two",

      "time": "13.02"

    },

    {

      "duration": "0.48",

      "confidence": "1.000",

      "name": "rams",

      "time": "13.26"

    },

    {

      "duration": "0.12",

      "confidence": "1.000",

      "name": "and",

      "time": "13.74"

    },

    {

      "duration": "0.06",

      "confidence": "0.990",

      "name": "a",

      "time": "13.86"

    },

 

 

 

아래와 같이 str 파일로 바꾸어야 한다.

 

12

12.93 --> 13.86

the two rams and a

 

 

/* This program converts a json file from Speechmatics to srt subtitle file. */
/* Usage is as follows. You need to type the below in the windows command line.

            json2srt num < example.json > output.srt

               where num is the maximum numbers of words you can have in a line.
               this number is optional and may not be entered. Then the number 10 will be
               used as deafult.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char buf[128];  /* read a line to buf */
char tmp[128]; /* it could be time or word. see the program code below. */
char ans[254];  /* accumulate words to ans */
char old[254];  /* save ans to old */
char old2[64];  /* save last(time) to old2 */

char first[64];   /* first time */
char last[64];   /* last time   */

int cnt; /* counter for words */
int knt; /* It's a counter that allows you to know how many lines you are printing. */

#define YES 1
#define NO 0

int usage( ) {

    puts("Usage is as follows.\n");
    puts("json2srt num < example.json > output.srt");
    puts("           where num is the maximum numbers of words you can have in a line.");
    puts("           this number is optional and may not be entered. Then the number 10 will be");
    puts("           used as deafult.");
    puts("");

    return 0;
}

int is_int(char str[ ] ) {
    char *p=str;
    
    for( ; p && *p ;  p++ )
         if( *p > '9' || *p < '0' ) {
            return NO;
         } 
    
    return YES;
}

int trim(char str[ ] ) {
    char *p=str;
    char *t=NULL;
    
    for( ; *p == ' ';   ) p++; /* left trim */
    strcpy(str, p);
 
    t= str + strlen(str);      /* right trim */
    for( ; *--t == ' ' ; );
    *( t + 1 ) = 0;

    return 0;    
}    

int time_string( char str[ ] ) {
    /* example input argument is like "5334.72" */
    
    char str2[128]; /* variable to hold the answer */
  
    float numf = 0;
    int   numi = 0;
    int hh, mm, ss, deci;
  
    numf = atof(str);
    numi = numf;
    hh = numi / 3600;
    mm = ( numi - hh * 3600 ) / 60;
    ss = ( numi - hh * 3600 - mm * 60);
    deci = (numf - numi) * 100;
  
    sprintf(str2, "%02d:%02d:%02d.%02d0", hh, mm, ss, deci);

    strcpy(str, str2); /* modifies passed argument. str will be passed to caller function. */

    return 0;
}

int print(int opt) {
    char first2[64];
    char last2[64];

    /* opt == 0 means when you don't have to try one more word */
    /* opt == 1 means when you have to try one more word */

    if(opt == 0) { 
      strcpy(ans, old);
      strcpy(last, old2);
    }

    trim(ans);
    if( strlen(ans) < 1 ) return 0;
    
    printf("%d\n", ++knt);
    strcpy(first2, first); time_string(first2); /* change to time string */
    strcpy(last2, last); time_string(last2);  /* change to time string */

    printf("%s --> %s\n", first2, last2);
    printf("%s\n\n", ans);

    strcpy(ans, "");
    cnt = 0;

    if(opt == 0 ) {
      strcpy(ans, tmp);
      strcpy(first, last);
      cnt = 1;
    }
 
    return 0;
}

int words_per_line;

int main(int argc, char *argv[ ] ) {

    char *p = NULL;

    ans[0]=0; knt  = 0; cnt=0; 
   
    if( argc > 2 ) {
       puts("Too many argments");
       usage( );
       return 0;
    }

    if( argc > 1 ) {
       if( is_int(argv[1]) == NO ) {
          puts("Err1. Argment must be an integer that is greater than zero."); puts("");
          usage( );
          return 0;
       } else {
          words_per_line = atoi(argv[1]);

          if( words_per_line == 0 ) {
            puts("Err2. Argment must be an integer that is greater than zero."); puts("");
            usage( );
            return 0;
         }
       }
    }
    else
        words_per_line = 10;

    /* Do nothing until you find the postion string 'word' in the file. */
    while( fgets(buf, 128-1, stdin) ) {
            if( strstr(buf, "words") ) break;
    }

    while( fgets(buf, 128-1, stdin) ) {
            
            buf[ strcspn(buf, "\n") ] =0; /* removes new line character */

            if( (p= strstr(buf, "time")) ) {
                strcpy(old2, last);
                strcpy(last, p+8);
                last[ strcspn(last, "\"") ] =0;
                if(cnt == 0) { strcpy(first, last); }
            } else
            if( (p= strstr(buf, "name")) ) {
                cnt++;
                strcpy(tmp, p+8);
                tmp[ strcspn(tmp, "\"") ] =0;
                strcat(tmp, " ");

                strcpy(old, ans); /* save ans to old before assigning new value. */
                if( strcmp(tmp, ". ") == 0 ) ans[ strlen(ans) - 1 ] =0;  
                strcat(ans, tmp);
                
               if( cnt == words_per_line + 1) { /* try one more time*/
                  if( strcmp(tmp, ". ") == 0 ) {
                     print(1);
                  } else {
                     print(0);
                  } /* if */
               }/* if */
            }/* if */
    }/* while */

    print(1);

    return 0;
}

 

자세한 사용방법은 추후에 올리기로 한다.

댓글