OSDN Git Service

add no audio encode checkbox
[cmcheckwave/cmcheckwave.git] / cmcheckwave.c
index 4513164..ca13b2b 100644 (file)
@@ -14,7 +14,17 @@ Usage: cmcheckwave filename.wav
 
 #include "tclist.h"
 
-static void usage(void){
+static void usage(char *cmd){
+       fprintf(stderr,"Check CM from wavefile(output cmd stdout)\n");
+       fprintf(stderr,"%s: filename.wav\n\n",cmd);
+       fprintf(stderr,"Check CM from mp4file(require ffmpeg or faad cmd)\n");
+       fprintf(stderr,"%s: filename.mp4\n\n",cmd);
+       fprintf(stderr,"Check CM from mp4file and execute cutcmd(create new filename.mp4-new.mp4) \n");
+       fprintf(stderr,"%s: -x filename.mp4\n\n",cmd);
+       fprintf(stderr,"Check CM and manual edit\n");
+       fprintf(stderr,"%s: -b filename.mp4 filename.mp4 > filename-sh\n",cmd);
+       fprintf(stderr,"Edit filename-sh for mis detection and re execute next cmd\n",cmd);
+       fprintf(stderr,"%s: -x filename-sh\n",cmd);
        exit(1);
 }
 
@@ -49,6 +59,9 @@ typedef struct {
        char cmflg;
        char honpen;
        int  peak;
+       int  stsecfix;
+       int  edsecfix;
+       char *fixparam;
 }muonst;
 
 static muonst m[1000];
@@ -61,19 +74,36 @@ static int defmax=9;
 static int thumb=0;
 static int txtrecheck=0;
 static int cmdexecute=0;
+static int checkcomplete=0;
+static int basets=0;
 
-static char *MP4BOXCMD="/usr/local/bin/MP4Box -quiet -noprog";
 static char *MP4BOXCMDRAPSTR="Adjusting chunk start time to previous random access at ";
+#ifdef __FreeBSD__
+static char *MP4BOXCMD="/usr/local/bin/MP4Box";
 static char *SOXCMD="/usr/local/bin/sox";
 static char *FFMPEGCMD="/usr/local/bin/ffmpeg";
 static char *MPLAYERCMD="/usr/local/bin/mplayer";
 static char *AACENCCMD="/usr/local/bin/aacplusenc";
+static char *AACENCOPT="%s '%s.wav' '%s' 60";
+static char *FAADCMD="/usr/local/bin/faad";
+static char *FIXASS="/usr/home/piro/bin/fixass";
+#else
+static char *MP4BOXCMD="MP4Box";
+static char *SOXCMD="sox";
+static char *FFMPEGCMD="ffmpeg";
+static char *MPLAYERCMD="mplayer";
+static char *AACENCCMD="neroAacEnc";
+static char *AACENCOPT="%s -br 60 -if '%s.wav' -of '%s'";
+static char *FAADCMD=NULL;
+static char *FIXASS="fixass";
+#endif
 
 FILE *checkMP4(FILE *f,char *filename)
 {
        char readbuf[20];
        char *cmdbuf;
        FILE *pp;
+       char *tmpts;
 
        memset(readbuf,0,sizeof(readbuf));
        fread(readbuf,sizeof(readbuf),1,f);
@@ -82,8 +112,23 @@ FILE *checkMP4(FILE *f,char *filename)
                return NULL;
        }
        // mp4ファイルだったら、ffmpegでwaveに変換し読み込む。
-       //sprintf(cmdbuf,"%s -v 0 -i %s -f wav pipe: 2>/dev/null",FFMPEGCMD,filename);
-       asprintf(&cmdbuf,"%s -v 0 -i %s -f wav pipe: 2>/dev/null",FFMPEGCMD,filename);
+       if (FAADCMD) {
+               // filename.tmp.ts is exist ?
+               asprintf(&tmpts,"%s.tmp.ts",filename);
+               if (basets && (pp=fopen(tmpts,"r") )) {
+                       fclose(pp);
+                       pp=NULL;
+               asprintf(&cmdbuf,"%s -d -w -F 0x3330D -q '%s'",FAADCMD,tmpts);
+               }
+               else {
+           asprintf(&cmdbuf,"%s -d -w -q '%s'",FAADCMD,filename);
+}
+               
+               free(tmpts);
+       }
+    else
+           asprintf(&cmdbuf,"%s -v 0 -i '%s' -f wav pipe: 2>/dev/null",FFMPEGCMD,filename);
+
        pp = popen(cmdbuf,"r");
        if (pp == NULL) return NULL;
        fclose(f);
@@ -109,7 +154,7 @@ int checkMP4RAP(int stsec,int edsec)
 
        if (wkfilename==NULL) return stsec;
 
-       sprintf(cmdbuf,"%s -splitx %.2f:%.2f %s -out /dev/null",MP4BOXCMD,edsec/1000.0,(edsec+10000)/1000.0,wkfilename);
+       sprintf(cmdbuf,"%s -quiet -noprog -splitx %.2f:%.2f '%s' -out /dev/null",MP4BOXCMD,edsec/1000.0,(edsec+10000)/1000.0,wkfilename);
 
        rap=0.0;
        pp = popen(cmdbuf,"r");
@@ -127,6 +172,85 @@ int checkMP4RAP(int stsec,int edsec)
        else return stsec;
 
 }
+int cmpinfo(int mcnt)
+{
+       int i;
+       char *cmdptr,readbuf[20];
+       TCLIST *cmdlist;
+
+       if (!wkfilename) return 0;
+
+       cmdlist = tclistnew();
+
+       asprintf(&cmdptr,"#!/bin/sh");
+       tclistpush2(cmdlist,cmdptr);
+       free(cmdptr);
+
+
+       for(i=0;i<mcnt;i++) {
+               if (thumb) {
+                       asprintf(&cmdptr,"rm -f '%s-%d.png'",wkfilename,i);
+                       tclistpush2(cmdlist,cmdptr);
+                       free(cmdptr);
+               }
+       }
+       // check new mp4
+       asprintf(&cmdptr,"%s-new.mp4",wkfilename);
+       FILE *fp;
+       fp = fopen(cmdptr,"rb");
+       if (fp==NULL) {
+               //ファイルなし
+               return 0;
+       }
+       fread(readbuf,sizeof(readbuf),1,fp);
+       if (!strstr(readbuf+4,"ftypisom")) {
+               //mp4じゃない感じ(置き換えないときは無視)
+               if (checkcomplete == 1) return 0;
+       }
+       fclose(fp);
+       free(cmdptr);
+
+       if (checkcomplete==1) { //元ファイル置き換え
+               asprintf(&cmdptr,"mv '%s-new.mp4' '%s'",wkfilename,wkfilename);
+               tclistpush2(cmdlist,cmdptr);
+               free(cmdptr);
+               asprintf(&cmdptr,"mv '%s.fix.ass' '%s.ass'",wkfilename,wkfilename);
+               tclistpush2(cmdlist,cmdptr);
+               free(cmdptr);
+       }
+       if (checkcomplete==2) { //CMカットファイル削除
+               asprintf(&cmdptr,"rm -f '%s-new.mp4'",wkfilename);
+               tclistpush2(cmdlist,cmdptr);
+               free(cmdptr);
+       }
+
+       asprintf(&cmdptr,"rm -f '%s-sh'",wkfilename);
+       tclistpush2(cmdlist,cmdptr);
+       free(cmdptr);
+
+       asprintf(&cmdptr,"rm -f '%s.split.log'",wkfilename);
+       tclistpush2(cmdlist,cmdptr);
+       free(cmdptr);
+
+       asprintf(&cmdptr,"rm -f '%s.fix.ass'",wkfilename);
+       tclistpush2(cmdlist,cmdptr);
+       free(cmdptr);
+
+       for(i=0;i<tclistnum(cmdlist);i++) {
+               if (cmdexecute) {
+                       FILE *pp;
+                       char pbuf[1024];
+                       pp = popen(tclistval2(cmdlist,i),"r");
+                       if (pp==NULL) {continue;}
+                       while(fgets(pbuf,1024,pp)!=NULL){
+                       }
+                       pclose(pp);
+               }
+               else
+                       printf("%s\n",tclistval2(cmdlist,i));
+       }
+
+}
 int dumpinfo(int mcnt)
 {
        int honstart,hcnt,totalsec;
@@ -134,6 +258,7 @@ int dumpinfo(int mcnt)
        char *cptr,*cptr2,*tfptr;
        TCLIST *cmdlist;
        TCLIST *tflist;
+       FILE *fp;
 
        honstart=0;
        hcnt=0;
@@ -141,26 +266,29 @@ int dumpinfo(int mcnt)
        printf("#!/bin/sh\n# cmcheckwave %s\n#\n",wkfilename?wkfilename:"");
        //カットするため、一連のCM,本編時間を結合
        for(i=0;i<mcnt;i++) {
-               printf("# %.2f %.2f diff %.2f %s\n",m[i].stsec/1000.0,m[i].edsec/1000.0,m[i].diffs/1000.0,m[i].cmflg?"CM":"");
+               printf("# %.2f %.2f diff %.2f ",m[i].stsec/1000.0,m[i].edsec/1000.0,m[i].diffs/1000.0);
+               if (m[i].cmflg==1) printf("CM\n");
+               else printf("%s\n",m[i].fixparam?m[i].fixparam:"");
+
                //本編開始位置をマーク
                if ((m[i].cmflg==0)&&(honstart==0)) {
                        honstart=1;
                        if (i==0) h[hcnt].stsec = 0;
-                       else h[hcnt].stsec = m[i-1].edsec+(defmuon*0.5);
+                       else h[hcnt].stsec = m[i-1].edsec+(defmuon*0.5) + m[i].stsecfix;
                }
                else {
                        //終了位置をマーク
                        if ((m[i].cmflg==1)&&(honstart==1)) {
                                honstart=0;
                                //h[hcnt].edsec = m[i-1].stsec;
-                               h[hcnt].edsec = checkMP4RAP(m[i-1].stsec,m[i-1].edsec);
+                               h[hcnt].edsec = checkMP4RAP(m[i-1].stsec,m[i-1].edsec) + m[i-1].edsecfix;
                                totalsec += h[hcnt].edsec - h[hcnt].stsec;
                                hcnt++;
                        }
                }
        }
        if (honstart==1) {
-               h[hcnt].edsec = checkMP4RAP(m[i-1].stsec,m[i-1].edsec);
+               h[hcnt].edsec = checkMP4RAP(m[i-1].stsec,m[i-1].edsec) + m[i-1].edsecfix;
                totalsec += h[hcnt].edsec - h[hcnt].stsec;
                hcnt++;
        }
@@ -169,10 +297,15 @@ int dumpinfo(int mcnt)
 
        cmdlist = tclistnew();
        tflist = tclistnew();
+       if (wkfilename) {
+               asprintf(&cptr,"rm -f '%s.split.log'",wkfilename);
+               tclistpush2(cmdlist,cptr);
+               free(cptr);
+       }
        for(i=0;i<hcnt;i++) {
                if (wkfilename) {
                        asprintf(&tfptr,"%s.%d%s",wkfilename,i,noaudioencode?".mp4":"");
-                       asprintf(&cptr,"%s -splitx %.2f:%.2f %s -out %s",MP4BOXCMD,h[i].stsec/1000.0,h[i].edsec/1000.0,wkfilename,tfptr);
+                       asprintf(&cptr,"%s -quiet -noprog -splitx %.2f:%.2f '%s' -out '%s' >> '%s.split.log'",MP4BOXCMD,h[i].stsec/1000.0,h[i].edsec/1000.0,wkfilename,tfptr,wkfilename);
                        tclistpush2(cmdlist,cptr);
                        tclistpush2(tflist,tfptr);
                        free(tfptr);
@@ -181,14 +314,17 @@ int dumpinfo(int mcnt)
                        if (!noaudioencode) {
                                asprintf(&tfptr,"%s.%d.wav",wkfilename,i);
 
-                               asprintf(&cptr,"%s -v 0 -i %s.%d -vn %s",FFMPEGCMD,wkfilename,i,tfptr);
+                               if (FAADCMD)
+                                       asprintf(&cptr,"%s -d -q -o '%s' '%s.%d' ",FAADCMD,tfptr,wkfilename,i);
+                               else
+                                       asprintf(&cptr,"%s -v 0 -i '%s.%d' -vn '%s'",FFMPEGCMD,wkfilename,i,tfptr);
                                tclistpush2(cmdlist,cptr);
                                tclistpush2(tflist,tfptr);
                                free(tfptr);
                                free(cptr);
 
                                asprintf(&tfptr,"%s.%d.mp4",wkfilename,i);
-                               asprintf(&cptr,"%s -v 0 -i %s.%d -an -vcodec copy %s",FFMPEGCMD,wkfilename,i,tfptr);
+                               asprintf(&cptr,"%s -v 0 -i '%s.%d' -an -vcodec copy '%s'",FFMPEGCMD,wkfilename,i,tfptr);
                                tclistpush2(cmdlist,cptr);
                                tclistpush2(tflist,tfptr);
                                free(tfptr);
@@ -196,59 +332,71 @@ int dumpinfo(int mcnt)
                        }
                }
                else {
-                       asprintf(&cptr,"# %s -splitx %.2f:%.2f ",MP4BOXCMD,h[i].stsec/1000.0,h[i].edsec/1000.0);
+                       asprintf(&cptr,"# %s -quiet -noprog -splitx %.2f:%.2f ",MP4BOXCMD,h[i].stsec/1000.0,h[i].edsec/1000.0);
                        tclistpush2(cmdlist,cptr);
                }
        }
        if (wkfilename) {
                if (!noaudioencode) {
-                       asprintf(&cptr2,"%s ",SOXCMD);
+                       asprintf(&cptr2,"%s --norm ",SOXCMD);
                        for(i=0;i<hcnt;i++) {
                                asprintf(&tfptr,"%s.%d.wav",wkfilename,i);
-                               asprintf(&cptr,"%s %s ",cptr2,tfptr);
+                               asprintf(&cptr,"%s '%s' ",cptr2,tfptr);
                                free(cptr2);
                                cptr2=cptr;
                                tclistpush2(tflist,tfptr);
                                free(tfptr);
                        }
                        asprintf(&tfptr,"%s.wav",wkfilename);
-                       asprintf(&cptr,"%s %s",cptr2,tfptr);
+                       asprintf(&cptr,"%s '%s'",cptr2,tfptr);
                        free(cptr2);
                        tclistpush2(cmdlist,cptr);
                        tclistpush2(tflist,tfptr);
                        free(tfptr);
 
                        asprintf(&tfptr,"%s.aac",wkfilename);
-                       asprintf(&cptr,"%s %s.wav %s 60",AACENCCMD,wkfilename,tfptr);
+                       asprintf(&cptr,AACENCOPT,AACENCCMD,wkfilename,tfptr);
                        tclistpush2(cmdlist,cptr);
                        free(cptr);
                        tclistpush2(tflist,tfptr);
                        free(tfptr);
                }
-               //再チェックの場合-new.mp4ファイルを削除する
-               if (txtrecheck) {
-                       asprintf(&cptr,"rm -f %s-new.mp4",wkfilename);
-                       tclistpush2(cmdlist,cptr);
-                       free(cptr);
-               }
-               asprintf(&cptr2,"%s",MP4BOXCMD);
+               //ファイル名-new.mp4ファイルを削除する
+               asprintf(&cptr,"rm -f '%s-new.mp4'",wkfilename);
+               tclistpush2(cmdlist,cptr);
+               free(cptr);
+
+               asprintf(&cptr2,"%s -quiet -noprog ",MP4BOXCMD);
                for(i=0;i<hcnt;i++) {
-                       asprintf(&cptr,"%s -cat %s.%d.mp4 ",cptr2,wkfilename,i);
+                       asprintf(&cptr,"%s -cat '%s.%d.mp4' ",cptr2,wkfilename,i);
                        free(cptr2);
                        cptr2=cptr;
                }
-               asprintf(&cptr,"%s %s-new.mp4",cptr2,wkfilename);
+               asprintf(&cptr,"%s '%s-new.mp4'",cptr2,wkfilename);
                tclistpush2(cmdlist,cptr);
                free(cptr);
 
                if (!noaudioencode) {
-                       asprintf(&cptr,"%s -add %s.aac %s-new.mp4",MP4BOXCMD,wkfilename,wkfilename);
+                       asprintf(&cptr,"%s -quiet -noprog -add '%s.aac' '%s-new.mp4'",MP4BOXCMD,wkfilename,wkfilename);
                        tclistpush2(cmdlist,cptr);
                }
 
+               /* wkfilename.mp4.assファイルがあったらfixassを実施  */
+               asprintf(&cptr,"%s.ass",wkfilename);
+               fp = fopen(cptr,"r");
+               if (fp) {
+                       free(cptr);
+                       fclose(fp);
+                       asprintf(&cptr,"%s '%s' > '%s.fix.ass'",FIXASS,wkfilename,wkfilename);
+                       tclistpush2(cmdlist,cptr);
+                       free(cptr);
+               }
+               else {
+                       free(cptr);
+               }
 
                for(i=0;i<tclistnum(tflist);i++) {
-                       asprintf(&cptr,"rm -f %s",tclistval2(tflist,i));
+                       asprintf(&cptr,"rm -f '%s'",tclistval2(tflist,i));
                        tclistpush2(cmdlist,cptr);
                        free(cptr);
                }
@@ -256,7 +404,7 @@ int dumpinfo(int mcnt)
                if (thumb) {
                        pre=0;
                        for(i=0;i<mcnt;i++) {
-                               asprintf(&cptr,"mplayer -ss %.2f -frames 1 -vo png  %s ; mv 00000001.png %s-%d.png",(pre + (m[i].stsec-pre)/2)/1000.0,wkfilename,wkfilename,i);
+                               asprintf(&cptr,"%s -ao null -ss %.2f -frames 1 -vo png:z=9  '%s' ; mv 00000001.png '%s-%d.png'",MPLAYERCMD,(pre + (m[i].stsec-pre)/2)/1000.0,wkfilename,wkfilename,i);
                                tclistpush2(cmdlist,cptr);
                                pre = m[i].stsec;
                        }
@@ -264,11 +412,11 @@ int dumpinfo(int mcnt)
        }
 
        for (i=0;i<tclistnum(cmdlist);i++) {
-               if (cmdexecute) {
+               if (cmdexecute && wkfilename) {
                        FILE *pp;
                        char pbuf[1024];
                        pp = popen(tclistval2(cmdlist,i),"r");
-                       if (pp==NULL) {printf("cmdfail %s\n",tclistval2(cmdlist,i));continue;}
+                       if (pp==NULL) {continue;}
                        while(fgets(pbuf,1024,pp)!=NULL){
                        }
                        pclose(pp);
@@ -318,12 +466,34 @@ int rechecktext(FILE *f)
                        m[cnt].edsec = (int)(atof(wk2)*1000.0);
                        m[cnt].diffs = (int)(atof(wk3)*1000.0);
                        if (strstr(wk4,"CM")) m[cnt].cmflg=1;
-                       else m[cnt].cmflg=0;
+                       else {
+                               m[cnt].cmflg=0;
+                               /* CMカット位置の調整パラメータ
+                                       -0.1, (開始位置を-0.1秒ずらす、終了位置はそのまま)
+                                       ,7    (開始位置そのまま、終了位置は7フレームずらす)
+                                       -0.5,10 (開始位置を-0.5秒、終了位置を10フレームずらす)
+                                       開始位置パラメータが有効なのはCMの直後
+                                       終了位置パラメータが有効なのは次がCMの場合のみとする。
+                               */
+                               if (strlen(wk4)>0) {
+                                       m[cnt].fixparam = strdup(wk4);
+                                       TCLIST *t = tcstrsplit(wk4,",");
+                                       if (tclistnum(t)==2) {
+                                               m[cnt].edsecfix = atoi(tclistval2(t,1))*33;
+                                       }
+                                       if (tclistnum(t)>=1) {
+                                               m[cnt].stsecfix = (int)(atof(tclistval2(t,0))*1000.0);
+                                       }
+                               }
+                       }
                        m[cnt].honpen = 0;
                        cnt++;
                }
 
        }
+       if (checkcomplete > 0) {
+               return cmpinfo(cnt);
+       }
        txtrecheck=1;
        return dumpinfo(cnt);
 
@@ -382,6 +552,8 @@ int cmcheckwave(FILE *f)
        }
 
        readed=max=totalsec=kankaku=mcnt=0;
+       memset(m,sizeof(m),0);
+       memset(h,sizeof(h),0);
        peak=0;
        muonstartsec=-1;
        loop=1;
@@ -511,14 +683,18 @@ int main(int argc, char *argv[])
        int i,ch;
        FILE *f,*p;
        int ret;
-       char *tmpenv;
+       char *tmpenv,*argv0;
        ret = -1;
 
-       while ((ch = getopt(argc, argv, "adtxb:m:v:")) != -1){
+       argv0 = argv[0];
+       while ((ch = getopt(argc, argv, "agdtxb:m:v:c:")) != -1){
                switch (ch){
                        case 'a':
                                noaudioencode=1;
                                break;
+                       case 'g':
+                               basets=1;
+                               break;
                        case 'd':
                                verbose=1;
                                break;
@@ -537,15 +713,19 @@ int main(int argc, char *argv[])
                        case 'x':
                                cmdexecute=1;
                                break;
+                       case 'c':
+                               checkcomplete=atoi(optarg);
+                               if (checkcomplete <= 0 && checkcomplete > 2) usage(argv0);
+                               break;
                        default:
-                               usage();
+                               usage(argv0);
                }
        }
        argc -= optind;
        argv += optind;
 
        if (argc != 1) {
-               usage();
+               usage(argv0);
                return 0;
        }
        if (tmpenv=getenv("FFMPEG")) FFMPEGCMD=tmpenv;
@@ -553,7 +733,12 @@ int main(int argc, char *argv[])
        if (tmpenv=getenv("MP4BOX")) MP4BOXCMD=tmpenv;
        if (tmpenv=getenv("MP4BOXCMDRAPSTR")) MP4BOXCMDRAPSTR=tmpenv;
        if (tmpenv=getenv("AACENC")) AACENCCMD=tmpenv;
-       if (tmpenv=getenv("MPLAYERCMD")) MPLAYERCMD=tmpenv;
+       if (tmpenv=getenv("AACENCPOT")) AACENCOPT=tmpenv;
+       if (tmpenv=getenv("MPLAYER")) MPLAYERCMD=tmpenv;
+       if (tmpenv=getenv("FAADCMD")) FAADCMD=tmpenv;
+#ifdef DEBUG
+       if ((FAADCMD) && (tmpenv=getenv("FORCEFFMPEGCMD"))) FAADCMD = NULL;
+#endif
 
        ret=0;
        p=NULL;