#1 2017-01-26 02:52

lanceru
Member
Registered: 2015-09-29
Posts: 10

Rename subtitle file based on ep number with video file names array

I have a show on my computer that's 50 episodes long. I had to get the subtitle files separately. I understand this could probably be done in the same amount of time by going to UserInput, and pasting the video file names in there, but I'd greatly appreciate furthering my programming knowledge in general.

This the name of the video files, which was then copied to a text file:

L:\Anime\00 Anime_Show\renamer sample\[AnimeShow][20][BDRIP][960x720][X264-10bit_AAC].mp4
L:\Anime\00 Anime_Show\renamer sample\[AnimeShow][21][BDRIP][960x720][X264-10bit_AAC].mp4
L:\Anime\00 Anime_Show\renamer sample\[AnimeShow][22][BDRIP][960x720][X264-10bit_AAC].mp4
L:\Anime\00 Anime_Show\renamer sample\[AnimeShow][23][BDRIP][960x720][X264-10bit_AAC].mp4
L:\Anime\00 Anime_Show\renamer sample\[AnimeShow][24][BDRIP][960x720][X264-10bit_AAC].mp4
L:\Anime\00 Anime_Show\renamer sample\[AnimeShow][25][BDRIP][960x720][X264-10bit_AAC].mp4

To obtain the video file name in Microsoft Windows 7:

  • Select all the video files

  • Hold the Shift key

  • Right click and select 'Copy as Path'.

  • {Unnecessary} Go into Microsoft Excel, to sort the names in order. Note that excel drops the "quotation" marks. You may optionally run the following in the column next to it: =MID(A1, FIND("[AnimeS", A1), FIND(".mp4", A1)- FIND("[AnimeS", A1)). I didn't use this shortened version in the text file though

  • Paste the values from Excel into a basic text editor like notepad

File names of subtitle files dragged into ReNamer:

Anime_Show_20.ssa
Anime_Show_21.ssa
Anime_Show_22.ssa
Anime_Show_23.ssa
Anime_Show_24.ssa
Anime_Show_25.ssa

This is the algorithm I came up with thus far in Lazarus, an IDE for FreePascal:

{$mode objfpc}
uses classes;
var
   VideoNames: TStringlist; {TStringlist is similar to a Java ArrayList}

   i: Integer;
   currentVideoEpisode, currentSubtitleEpisode: String;
   videoFileName: String;
   wsExample: WideString;

begin
    VideoNames := TStringList.Create;
    try
      VideoNames.LoadFromFile('L:\Anime\00 Anime_Show\renamer sample\filenames.txt');

      WriteLn('Total VideoNames: ', VideoNames.Count); {debugging purpose}

      {It seems ReNamer, will run this entire code for each of the
      dragged files individually, and they are presented by the variable
      'FileName' by default}
      for i := 0 to VideoNames.Count-1 do
          begin
          currentVideoEpisode := copy(VideoNames[i], 51, 2);
          {videoFileName := copy(VideoNames[i], 39, 57);}
          videoFileName := copy(VideoNames[i],
                        Pos('[Ani',VideoNames[i]),
                        Pos('.mp4', VideoNames[i])- Pos('[Ani',VideoNames[i]));
          writeln(currentVideoEpisode, ' ', videoFileName);  {debugging}

          {FileName is predefined in rename as a WideString type}
          {currentSubtitleEpisode := copy(FileName, 12, 2)}
          {copy is equivalent to a Java Substring function}

          {If (currentSubtitleEpisode = currentVideoEpisode) Then
              FileName:= videoFileName;}

          end;
    readln {debugging}

    finally
      VideoNames.Free;
    en

The algorithm is executable and does include commented pseudo code, to better explain what I'm trying to do.

I was hoping, if someone could please complete this 'Custom' rule for the program for me and anyone else that may wish to use it. If it is too time consuming, I don't mind putting some effort in the algorithm.

The following results in a compile error:

{$mode objfpc}
uses classes;
var
  VideoNames: TStringlist; {TStringlist is similar to a Java ArrayList}
  i: Integer;
  currentVideoEpisode, currentSubtitleEpisode: String;
  videoFileName: String;

begin
  VideoNames := TStringList.Create;
  try
  VideoNames.LoadFromFile('L:\Anime\00 Anime_Show\renamer sample\filenames.txt');

  for i := 0 to VideoNames.Count-1 do
    begin
    currentVideoEpisode := copy(VideoNames[i], 51, 2);
    currentSubtitleEpisode := copy(FileName, 12, 2)};
    {videoFileName := copy(VideoNames[i], 39, 57);}
    videoFileName := copy(VideoNames[i],
                  Pos('[Ani',VideoNames[i]),
                  Pos('.mp4', VideoNames[i]) - Pos('[Ani',VideoNames[i]));
    {copy is equivalent to a Java Substring function}

    If (currentSubtitleEpisode = currentVideoEpisode) Then
      FileName := videoFileName;
    end;
    finally
      VideoNames.Free;
    end;
end.               

PS

[list=1] only allows number 1

Last edited by lanceru (2017-01-26 06:13)

Offline

#2 2017-01-26 17:42

den4b
Administrator
From: den4b.com
Registered: 2006-04-06
Posts: 3,367

Re: Rename subtitle file based on ep number with video file names array

Lazarus and ReNamer's Pascal Script use the same Pascal syntax, but the list of available types, classes and functions is very different.

The documentation for ReNamer's Pascal Script is available here:
http://www.den4b.com/wiki/ReNamer:Pasca … :Functions

Here is an example script which demonstrates how to port your logic to ReNamer's Pascal Script:

const
  SourceFile = 'filenames.txt';
var
  VideoFiles: TAnsiStringArray;
  I: Integer;
begin
  VideoFiles := FileReadLines(SourceFile);
  for I := 0 to Length(VideoFiles) - 1 do
  begin
    // ...
    // if found matching video file then
    // ...
    FileName := VideoFiles[I];
  end;
end.

Alternatively, instead of using a manually created lookup list of filenames, you could scan the subtitle's directory for MP4 files using WideScanDirForFiles function.

Offline

#3 2017-01-26 18:40

lanceru
Member
Registered: 2015-09-29
Posts: 10

Re: Rename subtitle file based on ep number with video file names array

Thanks for responding, I was able to gain a great leap with the following:

const
  SourceFile = 'L:\Anime\00 Anime_Show\renamer sample\filenames.txt';
var
  VideoFiles: TAnsiStringArray;
  I: Integer;
  currentVideoEpisode, currentSubtitleEpisode: String;
  videoFileName: String;
begin
  VideoFiles := FileReadLines(SourceFile);
  for I := 0 to Length(VideoFiles) - 1 do
  begin
    currentVideoEpisode := copy(VideoFiles[i], 51, 2);
    currentSubtitleEpisode := copy(FileName, 12, 2)};
    {videoFileName := copy(VideoNames[i], 39, 57);}
    videoFileName := copy(VideoFiles[i],
                  Pos('[Ani',VideoFiles[i]),
                  Pos('.mp4', VideoFiles[i]) - Pos('[Ani',VideoFiles[i]));

    If (currentSubtitleEpisode = currentVideoEpisode) Then
      FileName := videoFileName;
  end;
end.    

When I click compile, the error states that there's a syntax error at line 13 and an unexpected end to the file at that same line:

  • Line 13: currentSubtitleEpisode := copy(FileName, 12, 2)};

I would definitely like to use the function WideScanDirForFiles, once I get the current algorithm up an running.   

I came up with the following: WideScanDirForFiles('L:\Anime\00 Anime_Show\renamer sample\', '...\renamer sample\', false, false, false, '*.mp4')
From there I'm guessing I can retrieve the value of the 2nd argument for the StringArray.

+----------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
|                                    procedure                                     |                          You can get a list of the files inside a folder.                           |
+----------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| WideScanDirForFiles(const Dir: WideString; var Files: TStringsArray;             | Dir: The folder you want to scan.                                                                   |
|                                                                                  | Files: Where the list of files is going to be saved.                                                |
|                                                                                  | Recursive: Do you want to scan the subfolders?                                                      |
| const Recursive, IncludeHidden, IncludeSystem: Boolean; const Mask: WideString); | IncludeHidden: Do you want to list the hidden files?                                                |
|                                                                                  | IncludeSystem: Do you want to list the system files?                                                |
|                                                                                  | Mask: You can list everything ('*'), or only the files that contain some string (example: '*.txt'). |
+----------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+

Last edited by lanceru (2017-01-26 18:41)

Offline

#4 2017-01-26 20:18

Stefan
Moderator
From: Germany, EU
Registered: 2007-10-23
Posts: 1,161

Re: Rename subtitle file based on ep number with video file names array

lanceru wrote:

When I click compile, the error states that there's a syntax error at line 13 and an unexpected end to the file at that same line:

Line 13: currentSubtitleEpisode := copy(FileName, 12, 2)};





 


Read the  *WIKI* for HELP + MANUAL + Tips&Tricks.
If ReNamer had helped you, please *DONATE* to Denis or buy a PRO license. (Read *Lite vs Pro*)

Offline

#5 2017-01-26 22:28

lanceru
Member
Registered: 2015-09-29
Posts: 10

Re: Rename subtitle file based on ep number with video file names array

Thank you.

const
  SourceFile = 'L:\Anime\00 Anime_Show\renamer sample\filenames.txt';
var
  VideoFiles: TAnsiStringArray;
  I, videoEpPOS, subEpPOS: Integer;
  currentVideoEpisode, currentSubtitleEpisode: String;
  videoFileName, subExtension: String;
begin
  VideoFiles := FileReadLines(SourceFile);
  subExtension := WideCopyRight(FileName, 1, 4);

  videoEpPOS := Pos('[20]', VideoFiles[0]) + 1;     {must manually specify  ep# of file in 0th index}
  subEpPOS := Pos('_01', 'Anime_Show_01') + 1;
  for I := 0 to Length(VideoFiles) - 1 do
  begin
    currentVideoEpisode := copy(VideoFiles[i], videoEpPOS, 2);
    currentSubtitleEpisode := copy(FileName, subEpPOS, 2);

    videoFileName := copy(VideoFiles[i],
                  Pos('[Ani',VideoFiles[i]),
                  Pos('.mp4', VideoFiles[i]) - Pos('[Ani',VideoFiles[i]));

    If (currentSubtitleEpisode = currentVideoEpisode) Then
      FileName := videoFileName + subExtension;
  end;
end.

When executing the following statement:

FileName := videoFileName;

Is there a built in function in ReNamer to leave the file extension of FileName alone?
Otherwise I'd have to store RightStr(FileName, 4)/WideCopyRight(FileName, 1, 4) as variable and then append it to the renamed FileName.

Additionally I'm attempting the WideScanDirForFiles method, instead of importing a text file. The last argument, '*.mp4', seems cause a type mismatch error (i isolated it to its own line by pressing return after the comma).

var
  VideoFiles: TAnsiStringArray;
  I, videoEpPOS, subEpPOS: Integer;
  currentVideoEpisode, currentSubtitleEpisode: String;
  BasePath, videoFileName, subExtension: String;
begin
  BasePath := WideExtractFilePath(FilePath);
  WideScanDirForFiles(BasePath, VideoFiles, False, False, False, '*.mp4');

  subExtension := (RightStr(FileName, 1, 4));

  videoEpPOS := Pos('[20]', VideoFiles[0]) + 1;    {must manually specify  ep# of file in 0th index}
  subEpPOS := Pos('_01', 'Anime_Show_01') + 1;


  for I := 0 to Length(VideoFiles) - 1 do
  begin
    currentVideoEpisode := copy(VideoFiles[i], videoEpPOS, 2);
    currentSubtitleEpisode := copy(FileName, subEpPOS, 2);
    videoFileName := WideExtractBaseName(VideoFiles[i]);

    If (currentSubtitleEpisode = currentVideoEpisode) Then
      FileName := videoFileName + subExtension;
  end;
end.                 

Last edited by lanceru (2017-01-27 01:19)

Offline

#6 2017-01-27 09:48

Stefan
Moderator
From: Germany, EU
Registered: 2007-10-23
Posts: 1,161

Re: Rename subtitle file based on ep number with video file names array

>>> Is there a built in function in ReNamer to leave the file extension of FileName alone?

var
  BaseName, Extension, pattern      : WideString;

begin
      ////set own basic variable:
      BaseName  := WideExtractBaseName(FileName);
      Extension := WideExtractFileExt(FileName);



>>> WideScanDirForFiles method,, seems cause a type mismatch error

Do you know what 'Wide' means?
I don't know out of my head if 'Unicode' is the right term here, but 'Wide' works like that.
And so that doesn't fit with "VideoFiles: TAnsiStringArray;" declaration (ANSI <> Unicode)
Try with "VideoFiles: TWideStringArray;"     Array of WideString
Ah, of course, I found the answer: http://www.den4b.com/wiki/ReNamer:Pasca … ring_types



 


Read the  *WIKI* for HELP + MANUAL + Tips&Tricks.
If ReNamer had helped you, please *DONATE* to Denis or buy a PRO license. (Read *Lite vs Pro*)

Offline

#7 2017-01-27 11:56

lanceru
Member
Registered: 2015-09-29
Posts: 10

Re: Rename subtitle file based on ep number with video file names array

I had no luck in changing the array type to TWideStringArray, or changing the variables BasePath, videoFileName to WideString. I do aplogize for saying '*.mp4' was the culprit. I pressed the return key before the 2nd argument, and it turns out VideoFiles at line 9, is responsible causing the mismatch error.

var
  VideoFiles: TWideStringArray;
  I, videoEpPOS, subEpPOS: Integer;
  currentVideoEpisode, currentSubtitleEpisode: String;
  BasePath, videoFileName: WideString;
begin
  BasePath := WideExtractFilePath(FilePath);
  WideScanDirForFiles(BasePath,
              VideoFiles, False, False, False, '*.mp4');

  {subExtension := RightStr(FileName, 1, 4)); }

  videoEpPOS := Pos('[01]', VideoFiles[0]) + 1;  {must specify ep# at 0th ndx}
  subEpPOS := Pos('_01', 'Anime_Show_01') + 1;


  for I := 0 to Length(VideoFiles) - 1 do
  begin
    currentVideoEpisode := copy(VideoFiles[i], videoEpPOS, 2);
    currentSubtitleEpisode := copy(FileName, subEpPOS, 2);
    videoFileName := WideExtractBaseName(VideoFiles[i]);

    If (currentSubtitleEpisode = currentVideoEpisode) Then
      FileName := videoFileName + WideExtractFileExt(FileName);
  end;
end. 

Offline

#8 2017-01-27 12:09

Stefan
Moderator
From: Germany, EU
Registered: 2007-10-23
Posts: 1,161

Re: Rename subtitle file based on ep number with video file names array

lanceru wrote:

I had no luck in changing the array type to TWideStringArray,

OK, I did take a closer look onto the wiki:

procedure WideScanDirForFiles(
const Dir: WideString;
var Files: TStringsArray;
const Recursive, IncludeHidden, IncludeSystem: Boolean;
const Mask: WideString);


Looks like that "var Files" needs an "TStringsArray"? (not Ansi and not Wide ?)




Can you try that?

var
  VideoFiles: TStringArray;

begin
  WideScanDirForFiles(BasePath, VideoFiles, False, False, False, '*.mp4');





" BasePath, videoFileName: WideString; " should be ok anyway.






 


Read the  *WIKI* for HELP + MANUAL + Tips&Tricks.
If ReNamer had helped you, please *DONATE* to Denis or buy a PRO license. (Read *Lite vs Pro*)

Offline

#9 2017-01-27 18:13

lanceru
Member
Registered: 2015-09-29
Posts: 10

Re: Rename subtitle file based on ep number with video file names array

Thank you again that did the trick.

var
  VideoFiles: TStringsArray;
  I, videoEpPOS, subEpPOS: Integer;
  currentVideoEpisode, currentSubtitleEpisode: String;
  BasePath, videoFileName, Extension: WideString;
begin
  BasePath := WideExtractFilePath(FilePath);
  WideScanDirForFiles(BasePath, VideoFiles, False, False, False, '*.mp4');

  Extension := WideExtractFileExt(FileName);{(RightStr(FileName, 1, 4)); }

  videoEpPOS := Pos('[01]', VideoFiles[0]) + 1;  {must specify ep# at 0th ndx}
  subEpPOS := Pos('_01', 'Anime_Show_01') + 1;

  for I := 0 to Length(VideoFiles) - 1 do
  begin
    currentVideoEpisode := copy(VideoFiles[i], videoEpPOS, 2);
    currentSubtitleEpisode := copy(FileName, subEpPOS, 2);
    videoFileName := WideExtractBaseName(VideoFiles[i]);

    If (currentSubtitleEpisode = currentVideoEpisode) Then
      FileName := videoFileName + Extension;
  end;
end.     

If anyone wishes to use or make this code more scalable, feel free to do so. I'll try to make determining videoEpPos and subEpPos (episode positions) better

Last edited by lanceru (2017-01-27 18:18)

Offline

#10 2017-01-31 10:59

den4b
Administrator
From: den4b.com
Registered: 2006-04-06
Posts: 3,367

Re: Rename subtitle file based on ep number with video file names array

Stefan wrote:

Looks like that "var Files" needs an "TStringsArray"? (not Ansi and not Wide ?)

TStringsArray is a deprecated alias for TWideStringArray:
ReNamer:Pascal_Script:Types#Extra_types

It will soon be replaced by TWideStringArray in function signatures and documentation, to avoid confusion. TStringsArray type declaration will remain for backwards compatibility.

Offline

Board footer

Powered by FluxBB