1

I have a simply formatted text file (Edit Decision List) with rows of numbers (timecode frame rate 25) followed by rows of properties (names etc.).

Ultimately I am trying to:

  1. retrieve the lines starting with * FROM CLIP NAME:   and the row/line (timecode) immediately above. On this line are Timecodes, there are 4 groups of numbers, each are expressed as 00:00:00:00 - or HH:MM:SS:FF or Hours, minutes, seconds, frames. Then I discard everything else.

  2. Use the first 2 number groups (they are start and end times) to derive duration.

  3. Then append duration to the Clip Name line.

  4. Save file as "SourceFileName".txt (original is .edl so they won't overwrite).

As my frame rate is 25 frames per second I was expecting to decompose each group into a frame count.

I expected to convert Timecode to 25 frames per second:

  • hours to frame time base (25fps) 1 hour = 1*60*(60*25) = 9000
  • minutes to frame time base (25fps) 1 minute = 1*(60*25) = 1500
  • seconds to frame time base (25fps) 1 second = 1*25f

That would make a group of 00:02:20:01 = 3501 frames

  • 3501 integer divide // 25 fps = 140 sec
  • 3501 modulo (%) 25 = 1 frame remainder

  • 140/60 = 2 min

  • 140%60 = 20 sec

Then I would subtract the first group from the second to find the difference. Once I have the difference I recompose the Frame Count to a timecode, just reversing the math.

I can't work out how to specify the name line then grab the preceding line for arithemetic using the first 2 of the 4 groups.

So far (not far) I've only established a way for the user to define the source file on their desktop.

Option Explicit
Dim fso, oFile, y

Set fso = CreateObject("Scripting.FileSystemObject")

'get user to open file name
y = InputBox("name of file to save")

'next line opens a file with that name 
Set oFile = fso.OpenTextfile(y & ".edl")

UPDATE: revised script, but I cannot even group the selected lines and their start/end values

Option Explicit
Dim fso, oFile, y, re, prev, line, matches

Set fso = createobject("Scripting.FileSystemObject")

'get user to open file name
y = inputbox("name of file to save")

'next line opens a file with that name 
Set oFile = fso.Opentextfile(y&".edl")

Do Until oFile.AtEndOfStream
    line = oFile.ReadLine
    'At this point the variable prev either is empty (during the first loop
    'cycle) or holds the content of the previous line.
    If Left(line, 21) = "*  FROM CLIP NAME:   " Then
        'do stuff here
        Set re = New RegExp
        re.Pattern = "C        (\d{2}:\d{2}:\d{2}:\d{2})    (\d{2}:\d{2}:\d{2}:\d{2})"
        matches = re.Execute(prev)
        'print each pair of prev & Pattern match
        prev = (line) & (matches)
        wscript.echo prev
        'don't know how to use submatch values
    End If

Loop

Sample .edl file:

TITLE: test logan
* COMMENT:  CREATED BY GRASS VALLEY FOR EDIUS (CMX-3600) 
001  0000     A     C        00:00:04:23 00:00:42:04 00:00:00:00 00:00:37:06
* FROM CLIP NAME:  12 - Tech Sexy - D Cebert - FFP170
002  0000     A     C        00:00:20:01 00:00:31:23 00:01:29:24 00:01:41:21
* FROM CLIP NAME:  03 - Web Of Deceit (Main) - J Woodall - SFT164
003  0000     A     C        00:00:31:23 00:00:31:23 00:01:41:21 00:01:41:21
M2   0000        025.0              00:00:31:23
003  0000     A     D    025 00:00:31:09 00:00:54:12 00:01:41:21 00:02:04:24
* EFFECT NAME: CROSS DISSOLVE
* FROM CLIP NAME:  03 - Web Of Deceit (Main) - J Woodall - SFT164
* TO CLIP NAME:  03 - Web Of Deceit (Main) - J Woodall - SFT164
M2   0000        025.0              00:00:31:09
004  0000     A2    C        00:01:15:08 00:01:31:24 00:01:48:04 00:02:04:20
* FROM CLIP NAME:  12 - Environs A - T Juckes, S Kidd - SCDV354
005  0000     A2    C        00:00:11:12 00:00:30:05 00:02:06:24 00:02:25:17
* FROM CLIP NAME:  13 - Contagion (Main) - J Woodall - SFT164
006  0000     A2    C        00:00:06:13 00:00:56:09 00:02:27:04 00:03:17:00
* FROM CLIP NAME:  03 - Web Of Deceit (Main) - J Woodall - SFT164
007  0000     A2    C        00:00:56:09 00:00:56:09 00:03:17:00 00:03:17:00
M2   0000        025.0              00:00:56:09
007  0000     A2    D    025 00:00:55:08 00:01:54:03 00:03:17:00 00:04:15:20
* EFFECT NAME: CROSS DISSOLVE
* FROM CLIP NAME:  03 - Web Of Deceit (Main) - J Woodall - SFT164
* TO CLIP NAME:  03 - Web Of Deceit (Main) - J Woodall - SFT164
M2   0000        025.0              00:00:55:08
008  0000     A2    C        00:01:15:08 00:01:37:12 00:05:04:10 00:05:26:14
* FROM CLIP NAME:  12 - Environs A - T Juckes, S Kidd - SCDV354
009  0000     A2    C        00:00:00:00 00:00:26:19 00:06:00:08 00:06:27:02
* FROM CLIP NAME:  38 - Signs Of Pollution - W Plass - SCDV354
010  0000     A2    C        00:00:25:08 00:01:13:03 00:06:39:16 00:07:27:11
* FROM CLIP NAME:  38 - Signs Of Pollution - W Plass - SCDV354
011  0000     A2    C        00:01:13:03 00:01:13:03 00:07:27:11 00:07:27:11
M2   0000        025.0              00:01:13:03
011  0000     A2    D    025 00:01:48:22 00:02:04:09 00:07:27:11 00:07:42:23
* EFFECT NAME: CROSS DISSOLVE
* FROM CLIP NAME:  38 - Signs Of Pollution - W Plass - SCDV354
* TO CLIP NAME:  38 - Signs Of Pollution - W Plass - SCDV354
M2   0000        025.0              00:01:48:22

I have to do this in VBScript so that we can run it on various user's Windows desktops. We can't install other executables or run from command prompts. I don't have privileges for admin installs.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
3pointedit
  • 117
  • 7

1 Answers1

1

Remember the previous line in a separate variable when reading the file:

Do Until oFile.AtEndOfStream
    line = oFile.ReadLine
    'At this point the variable prev either is empty (during the first loop
    'cycle) or holds the content of the previous line.
    If Left(line, 19) = "* FROM CLIP NAME:  " Then
        'do stuff here
    End If
    prev = line
Loop

Use a regular expression for extracting start and end timestamps.

Set re = New RegExp
re.Pattern = "        (\d{2}:\d{2}:\d{2}:\d{2}) (\d{2}:\d{2}:\d{2}:\d{2})"
Set matches = re.Execute(prev)

The timestamps are available as the first and second submatch of matches.

Beware, however, that some of the FROM CLIP NAME lines in your input file don't seem to be preceded by timestamp lines, so you'll need to handle that.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • Oh wow thanks, I wondered how to hold the line until second line is correct. I will dig into this expression although I don't understand how they are stored in re.Pattern? – 3pointedit May 14 '18 at 12:32
  • 1
    @3pointedit They're not. `re.Pattern` defines the *pattern* you want to match the lines against. `re.Execute` then matches that pattern against a given string (in this case the line in the variable `prev`). – Ansgar Wiechers May 14 '18 at 17:06
  • Can I use these matched timestamps as "lists" of some sort so I can perform arithmetic on each part? As i cannot see where they can be kept as a variable. When I run this expression at regex101 I see that they are in "group1" and "group2". How can I access these groups? – 3pointedit May 15 '18 at 05:48
  • The timestamps are extracted as strings. Further transformations are required before you could use the data in arithmetic operations. For further help with that please post a new question. As for accessing the capturing groups (submatches in VBScript terms), please see the link in my answer. I put it there for a reason. Pay particular attention to the section "Extracting Substrings". – Ansgar Wiechers May 15 '18 at 07:35
  • Oh ok, thank you. I really appreciate your assistance. I find it hard to discern the difference between variable names vs functions – 3pointedit May 15 '18 at 07:44
  • @3pointedit Please do not move the target. If you have a new or followup question: post a new question. If you find that an answer to your current question resolved the problem described in that question: please consider accepting that answer. – Ansgar Wiechers May 21 '18 at 08:48
  • To be clear is the first part saying - keep this line if the next part says "* FROM CLIP NAME: ", is this right? So I need at least to make a following exclusion for lines that don't fit the pattern? Is this the right track? – 3pointedit May 23 '18 at 07:40
  • No. It's saying "do something only if the current line begins with the string '...'". You need to remember the line irrespective of that, so you can look into the past in the next iteration of the loop. VBScript can't look into the future, so it wouldn't know what it will read next. – Ansgar Wiechers May 23 '18 at 08:03
  • Oh. So I need to grab the timestamp string as a separate entity AND its following name string but only if they follow a certain pattern. So I should define that pattern first, but I can only loop per line, not per pair of lines? Should I start another question page and ask this? – 3pointedit May 23 '18 at 08:13
  • In the first iteration `line` contains the 1st line, `prev` is undefined. At the end of the iteration `prev` is assigned the value of `line` (i.e. the 1st line). In the next iteration `line` contains the 2nd line, `prev` contains the first line. At the end of the iteration `prev` is again assigned the value of `line` (i.e. the 2nd line). In the next iteration `line`contains the 3rd line, `prev` contains the 2nd line. And so on. Meaning that when `line` begins with the CLIP NAME string, `prev` already contains the timestamp line. Is it clearer now? – Ansgar Wiechers May 23 '18 at 11:21
  • I think so... I will try and get a WScript.Echo of these 2 variables to see the change. The RegExp should go inside the If loop right? – 3pointedit May 23 '18 at 11:41
  • Ok after all of that misunderstanding on my part I can get the if clause to work, but it errors on the line "matches = re.Execute(prev)" - Wrong number of arguments or invalid property assignment. Is it complaining about the variable "prev"? – 3pointedit May 24 '18 at 06:39
  • Ah, that's my mistake. You need the `Set` keyword there, b/c you're assigning an object. Fixed. – Ansgar Wiechers May 24 '18 at 06:46
  • If matches is not a string variable, what is it? I cannot simply Echo it to display? I'm guessing that I need to look at the submatches in match? If I know the type of object I could go figure it out :D – 3pointedit May 24 '18 at 07:19
  • Shouldn't it be "WScript.Echo matches.SubMatches"? – 3pointedit May 24 '18 at 07:31
  • When in doubt, read the [documentation](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/y27d2s18%28v%3dvs.84%29). – Ansgar Wiechers May 24 '18 at 09:32
  • Last reply at this question to say thank you. I did RTFM ;-) and integrated yours with the other solution. Will post any new questions away from here. – 3pointedit May 25 '18 at 01:26