Import and Export Text Layer Advice

Find out why the . goes before the /

Moderator: Paul Tuersley

Post Reply
Melanie K
Posts: 4
Joined: November 9th, 2016, 4:52 am

Hiya!
 
I am trying to automate a workflow with my client’s subtitles. 
I have tried many things! Here the history (which you can skip if you want as my main query is further down)
 
STEP 1
I receive a SRT file (which is just a text document, in this format https://en.wikipedia.org/wiki/SubRip) from a transcriber and bring it into AE using this script:
https://github.com/908video/DCSubToAE
This creates a single text layer with markers for each of the captions
 
STEP 2 (not necessarily needed but I like to see the cuts visually, and to help with my potential STEP 4)
I use this plugin to split that single layer into lots of text layers based on the markers
http://aescripts.com/pt_layermarkers/
 
STEP 3
I make some adjustments to the in and out points as the transcriber has slightly misjudged some of the timings. I then get this signed off and this becomes my master subtitle set.
 
Now here are where my issues with this are:
ISSUE 1
I would like to have a STEP 4 where I export the layers as a new SRT to be sent off for versioning into other languages so that when I bring it back in it all matches my signed off tweaks - rather than the versioning being based on the original SRT that I received. I used this script to export:
viewtopic.php?f=3&t=2116
However the problem seems to be that because the text is based on Markers, it doesn't read this and therefore gives me the timecodes with nothing in it.
Really I want to be able to just use the timecode instead of the SRT format because not many players actually show milliseconds so the transcriber has to have a certain one.
 
ISSUE 2
As the text is based on the marker copy I am not able to highlight certain words (my work around at the moment is using the fill and setting the range to be word based and moving the offset). Is it possible to make the text live again or due to the expression it can only be edited within the marker?
 
 
SO this brings me onto here as I posted that question a while ago on a forum and got no answers so decided to give up on that route entirely and simplify the process with some scripts.
 
To begin with I typed in 3 text layers manually (no markers involved)
I then modified the export script to give me a file that looks like this:
 

Code: Select all

00:00:01:23


00:00:02:14


Hello! My name is Test Subject.


I am here to talk about subtitles


 


 


00:00:02:14


00:00:04:05


I love subtitles. I wish I could


have all the subtitles ever.


 


 


00:00:04:05


00:00:05:21


I mean, who doesn’t love subtitles.
 
I then want to be able to import that back in (with updated language version)
 
I have used this script from Motion Scripts:

Code: Select all

{

  // create undo group

  app.beginUndoGroup("Create Text Layers From File");

  // Prompt user to select text file

  var myFile = File.openDialog("Please select input text file.");
  if (myFile != null){

    // open file
    var fileOK = myFile.open("r");
    if (fileOK){

      // create project if necessary

      var proj = app.project;
      if(!proj) proj = app.newProject();

      // create new comp named 'my text comp'

      var compW = 1920; // comp width
      var compH = 1080; // comp height
      var compL = 30;  // comp length (seconds)
      var compRate = 25; // comp frame rate
      var compBG = [0/255,0/255,0/255] // comp background color
  
      var myItemCollection = app.project.items;
      var myComp = myItemCollection.addComp('my text comp',compW,compH,1,compL,compRate);
      myComp.bgColor = compBG;

      // read text lines and create text layer for each
      // until end-of-file is reached

      var text;
      while (!myFile.eof){
        text = myFile.readln();layer
        if (text == "") text = "\r" ;
        myComp.layers.addText(text);
      }

      // close the file before exiting

      myFile.close();

    }else{
      alert("File open failed!");
    }
 
  }else{
    alert("No text file selected.");
  }

  app.endUndoGroup();
}
 
Though doesn’t quite do what I want it to.
 Ultimately I want to look at this bit:

Code: Select all

[size=100][/size]


      var text;
      while (!myFile.eof){
        text = myFile.readln();layer
        if (text == "") text = "\r" ;
        myComp.layers.addText(text);
      }
And say
Read first line. This is timecode in of layer 1
Read second line. This is timecode out of layer 1
Read third line. This is first line of text layer 1
Read fourth line. This is second line of text layer 1
Read fifth line. This is a break. Stop process but repeat until end of file.
 
Is this possible at all or have I gone completely down a rabbit hole? Any help would be much appreciated! My coding is very basic so I just wanted to check if it was even possible before spending too much more time on it.
 
Cheers,
Mel
 
runegan
Posts: 22
Joined: November 4th, 2016, 3:18 pm
Contact:

That is definitely doable.

Here is one way to do it:

Code: Select all

var currentlayer = null;
var foundTimecodes = 0;
var foundlines = 0;
var currentText = null;

var text, inPoint, outPoint, tc;
while (!myFile.eof) {
    text = myFile.readln();

    // Skip empty lines
    if ( lineIsEmpty(text) ) {
        continue; // Go to next line
    }

    if ( isTimecode(text) ) {
        foundTimecodes++;
        tc = currentFormatToTime(text, myComp.frameRate);

        // The first timecode for the new set
        if ( foundTimecodes % 2 === 1 ) {

            // Place the text on the previous layer
            if ( currentText !== null && currentlayer !== null  ) {
                insertCurrenttext(); // Sets currentlayer to null
            }

            // Create a new layer for the new set
            if ( currentlayer === null ) {
                currentlayer = myComp.layers.addText("");
            }

            currentlayer.inPoint = tc;
        } else {
            currentlayer.outPoint = tc;
        }

    // Collect all other lines into a variable
    } else {
        foundlines++;
        if ( foundlines % 2 === 1 ) {
            currentText = text;
        } else {
            currentText += "\n" + text;
        }
    }
}
insertCurrenttext(); // Insert text for the last lines

// Removes whitespace at beginning of line, such at newlines and spaces
function removeWhitespace(text) {
    return text.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
}

function lineIsEmpty( text ) {
    return removeWhitespace(text) === "";
}

function isTimecode(text) {
    // \d is a number 0-9. returns true if the pattern was found in the string[/font][/size]
    return /\d\d:\d\d:\d\d/.test( text );
}

function insertCurrenttext() {
    currentlayer.property("Source Text").setValue(currentText);
    currentText = null;
    currentlayer = null;
}
 
This is using the script you posted and replacing the lines you mentioned.
The biggest takeaway here is probably using a regular expression to find timecode lines, and using modulo to find out if the timecode is the in or out point.
Melanie K
Posts: 4
Joined: November 9th, 2016, 4:52 am

Oh my goodness you are amazing!!
I've just added this into the original code (via some terrible formatting on my side) and off the bat it WORKS.
Thank you so much!! I'm going to go through each bit and try and understand what it all means/how its working so you may see me come back later with some questions.

That is so kind of you to have worked that up! Much appreciated!

I'm going to do some more testing on both the import and export parts to make sure they are durable, and post both modified scripts here after that.

Ah thanks again!
Melanie K
Posts: 4
Joined: November 9th, 2016, 4:52 am

Aw runegan, I'm sorry, I broke it!

When there are 3 singled line captions in a row, the last caption at the end only has the bottom line in it (I've copied it into the code as I can't seem to attach a text file...)

Code: Select all

00:00:01:23
00:00:02:14
Hello! My name is Test Subject.
I am here to talk about subtitles

00:00:02:14
00:00:04:05
I love subtitles. I wish I could
have all the subtitles ever.

00:00:04:05
00:00:05:21
I mean, who doesn’t love subtitles.

00:00:07:21
00:00:08:15
Wait, what if it’s 1 line?

00:00:08:20
00:00:09:20
Like, 3 lots of 1 liners?

00:00:09:21
00:00:10:18
Oh dear, I have broken this.
I need to fix this!
I've been looking at the code and I don't quite understand how its creating the text layer I'm afraid (due to my lack of java knowledge!) so I'm a bit stumped as to how to troubleshoot. Is it this bit below that's inputting the text into the layer? 

Code: Select all

          // Collect all other lines into a variable
          } else {
            foundlines++;
            if ( foundlines % 2 === 1 ) {
              currentText = text;
          } else {
              currentText += "\n" + text;
          }

I thought maybe in the export file I create a way that it writes (null) into the empty 2nd line, and then in the import script get (null) to be replaced by a break but thought then again thats a really long winded way of doing it.

It gets all the timecode parts right, just the actually text layer it's potentially getting confused when there's not 2 lines.

You've been amazing help as it is so no worries if I'm asking too much!

Many thanks,
Mel
User avatar
conigs
Posts: 3
Joined: November 4th, 2016, 11:01 am
Contact:

From looking at the code… I think you’d just need to change how foundlines works… After the inPoint is loaded, reset foundlines…

Code: Select all

    if ( currentlayer === null ) {
        currentlayer = myComp.layers.addText("");
    }

    currentlayer.inPoint = tc;
    //Add this line
    foundlines = 0;
} else {
I think foundlines is getting tripped up and thinking the second line is really the first. This should fix that by resetting the counter for each new caption.
runegan
Posts: 22
Joined: November 4th, 2016, 3:18 pm
Contact:

The problem is the line:

Code: Select all

if ( foundlines % 2 === 1 ) {
Which will return true for every other line of text, this works for the timecode because they are always in a set of two, but not for the text.
Since the insertCurrenttext function set currentText to null when the text gets inserted into the text layer, you can use replace the above line with:

Code: Select all

if ( currentText === null ) {
You can then also discard the foundlines variable, since it isn't used.
Melanie K
Posts: 4
Joined: November 9th, 2016, 4:52 am

Thank you both so much!

Conig I added the line you suggested and it works absolutely fine!

Runegan I haven't tried replacing that line yet but will give it a go.

I'm going to test this out some more!!
Post Reply