Lire un fichier .srt

Ce script est basé sur celui de Flong, le site de Golan Levin. Il lui est ajouté une fonction de lecture synchronisée. On peut aussi se déplacer dans la ligne de temps en cliquant dans la partie inférieure de la fenêtre. Le script peut être téléchargé directement.

Précédent | 22/26 | Suivant

Voici le script, annoté à l’arrache :

/**************

This is a Processing parser for .SRT files, a widely used subtitle text file format.
.SRT file information is obtained from: http://en.wikipedia.org/wiki/SubRip

The SubRip file format is "perhaps the most basic of all subtitle formats."
SubRip files are named with the extension .srt,
and contain formatted UTF-8 plain text.
The time format used is hours:minutes:seconds,milliseconds.
The decimal separator used is the comma,
since the program was written in France;
the line break used is the CR+LF pair.
Subtitles are numbered sequentially, starting at 1.
The format for an .SRT subtitle is:

Subtitle number
Start time --> End time
Text of subtitle (one or more lines)
Blank line

These are parsed into a series of SubtitleUnit data structures
and stored in the Java Vector, subtitleVector.
(See class definition for SubtitleUnit below.)

***************/
//-----------------------------------------------------------
// Which .SRT file should we load (from the sketch's "data" folder)?
String srtFilename = "THX_1138.srt";

int compteur=0;
String sub_text="";
int adjuster;

//-----------------------------------------------------------
void setup() {
 size(600, 400);
 textAlign(CENTER, CENTER);
 subtitleVector = new ArrayList();
 creervecteur();
 // recuperer le passage du dernier sous-titre
 SubtitleUnit SU=(SubtitleUnit) subtitleVector.get(subtitleVector.size()-1);
 length_srt=SU.endTime+5000;
 
 adjuster=millis(); // commencer le compteur maintenant
}

void draw() {
 background (0);
 fill(255);

 int this_moment=millis()-adjuster;

 if (this_moment > sub_end) {
   compteur++;
   new_subtitle();

   if (compteur > subtitleVector.size()-1) { // retourner au début
     compteur=0;
   }
 }
 if (this_moment > sub_start && this_moment < sub_end) {
   text(sub_text, width/2, height*0.4);
 }
 text("compteur "+compteur + " - " + sub_text, width/2, height*40);

 text(this_moment, width/2, height*0.60);
 text(sub_start + " - "+ sub_end, width/2, height*0.66);

 // dessiner la barre de défilement
 noStroke();
 fill(0, 100, 10);
 rect(0, height-20, width, 20);
 stroke(255);
 float p=map(millis()-adjuster, 0, length_srt, 0, width);
 line(p, height-20, p, height);
}

void mouseClicked() {
 if (mouseY > height-20) {
   adjuster=millis()-int(map(mouseX, 0, width, 0, length_srt));
   find_subtitle();
 }
}
// toutes les fonctions de traitement des sous-titres
//-----------------------------------------------------------
// Important booleans which modify how we will perform the parsing.
boolean bStripItalicChars   = true;  // Remove <i> and </i>
boolean bStripOtherChars    = true;  // Remove initial hyphens and ellipses
boolean bStripMusicChars    = true;  // Remove #, indicating music
boolean bStripStagingChars  = false; // Remove brackets [ and ], indicating instructions
boolean bConvertToLowerCase = true;  // Convert all subtitles to lowercase

String rawSRTLines[];
int    nRawSRTLines;
int    nSubtitles;
ArrayList subtitleVector;
int sub_start;
int sub_end;
int length_srt;

//-----------------------------------------------------------
// Different codes for subtitles.

int SUBTITLE_TYPE_SPEECH  = 0;
int SUBTITLE_TYPE_MUSIC   = 1;
int SUBTITLE_TYPE_STAGING = 2;
int SUBTITLE_TYPE_ITALIC  = 3;
String typeStrs[] = {
 "SPEECH", "MUSIC", "STAGING", "ITALIC"
};

//-----------------------------------------------------------
// This class contains a single Subtitle: what was said when.
class SubtitleUnit {
 int    subtitleNumber;
 int    subtitleType;
 int  startTime;
 int  endTime;
 String subtitleText;

 void print() {
   String typeStr = typeStrs[subtitleType];
   println(subtitleNumber + "\t" + typeStr + "\t" + startTime + "\t" + endTime + "\t" + subtitleText);
 }
}

// ============================================== ici on crée les elements de sous-titre

void creervecteur() {
 
 rawSRTLines    = loadStrings(srtFilename);
 nRawSRTLines   = rawSRTLines.length;

 if (nRawSRTLines > 0) {
   String prevLine = rawSRTLines[0];
   String currLine = "";
   for (int i=1; i<nRawSRTLines; i++) {
     currLine = rawSRTLines[i];
     int indexOfArrowChars = currLine.indexOf("-->");

     if (indexOfArrowChars > -1) {
       // if we're here, then currLine is a timecode line, and prevline is an ID line
       int subtitleType   = SUBTITLE_TYPE_SPEECH;
       int subtitleID     = Integer.parseInt (prevLine.trim());
       String startString = currLine.substring (0, indexOfArrowChars);
       String endString   = currLine.substring (indexOfArrowChars+4, currLine.length());
       startString        = startString.trim();
       endString          = endString.trim();

       // Extract and compute the start and end timestamps of the subtitle.
       int sH = Integer.parseInt( startString.substring(0, 2));
       int sM = Integer.parseInt( startString.substring(3, 5));
       int sS = Integer.parseInt( startString.substring(6, 8));
       int sL = Integer.parseInt( startString.substring(9, 12));
       float startTimeInSeconds = 60*60*sH + 60*sM + sS + sL/1000.0;

       int eH = Integer.parseInt( endString.substring(0, 2));
       int eM = Integer.parseInt( endString.substring(3, 5));
       int eS = Integer.parseInt( endString.substring(6, 8));
       int eL = Integer.parseInt( endString.substring(9, 12));
       float endTimeInSeconds = 60*60*eH + 60*eM + eS + eL/1000.0;

       // Subtitles might be on several lines. Search ahead to find the end.
       String subtitle = "";
       int lineNumberToStartFrom = i;
       String futureLine = currLine;
       while ( (lineNumberToStartFrom< (nRawSRTLines-1)) && (futureLine.length() != 0)) {
         lineNumberToStartFrom++;

         futureLine = rawSRTLines[lineNumberToStartFrom];
         subtitle += futureLine + " ";
       }

       // Cleanup phase: clean the text.
       subtitle = subtitle.trim();
       if (bConvertToLowerCase) {
         subtitle = subtitle.toLowerCase();
       }

       //----------------------------------------
       if (subtitle.startsWith("#")) {
         subtitleType = SUBTITLE_TYPE_MUSIC;
       }
       if (subtitle.startsWith("[")) {
         subtitleType = SUBTITLE_TYPE_STAGING;
       }
       if (subtitle.startsWith("<i>")) {
         subtitleType = SUBTITLE_TYPE_ITALIC;
       }

       //----------------------------------------
       if (bStripItalicChars) {
         if (subtitle.startsWith("<i>")) {
           subtitle = subtitle.substring(3, subtitle.length());
         }
         if (subtitle.endsWith("</i>")) {
           subtitle = subtitle.substring(0, subtitle.length()-4);
         }
       }
       if (bStripOtherChars) {
         if (subtitle.startsWith("-")) {
           subtitle = subtitle.substring(1, subtitle.length());
         }
         if (subtitle.startsWith("...")) {
           subtitle = subtitle.substring(3, subtitle.length());
         }
       }
       if (bStripMusicChars) {
         if (subtitle.startsWith("#")) {
           subtitle = subtitle.substring(1, subtitle.length());
         }
         if (subtitle.endsWith("#")) {
           subtitle = subtitle.substring(0, subtitle.length()-1);
         }
       }
       if (bStripStagingChars) {
         if (subtitle.startsWith("[")) {
           subtitle = subtitle.substring(1, subtitle.length());
         }
         if (subtitle.endsWith("]")) {
           subtitle = subtitle.substring(0, subtitle.length()-1);
         }
       }
       // One more trim for good luck.
       subtitle = subtitle.trim();

       //----------------------------------------
       // Create a new Subtitle containing the above data,
       // and append it to the Vector of subtitles.

       SubtitleUnit SU = new SubtitleUnit();
       SU.subtitleNumber = subtitleID;
       SU.subtitleType   = subtitleType;
       SU.startTime = int(startTimeInSeconds*1000);
       SU.endTime = int(endTimeInSeconds*1000);
       SU.subtitleText   = subtitle;

       //subtitleVector.addElement(SU);
       
       subtitleVector.add(SU);
       nSubtitles++;
     }
     prevLine = currLine;
   }
 }
}

void new_subtitle() {
 SubtitleUnit SU = (SubtitleUnit) subtitleVector.get(compteur);
 sub_text=SU.subtitleText;
 sub_start=SU.startTime;
 sub_end=SU.endTime;
}

void find_subtitle() {
 for (int i=0;i<subtitleVector.size();i++) {
   SubtitleUnit SU = (SubtitleUnit) subtitleVector.get(i);
   if (SU.endTime > millis()-adjuster) {
     compteur=i;
     new_subtitle();
     break;
   }
 }
}