Jump to content

Recommended Posts

sundevil67
Posted
On 2/6/2025 at 8:39 PM, mickle026 said:

I can do this internally within Emby - I have my own plugin that does it. 
I actually just saw this post because I did a little coding on it today to fix a bug and was reading the forum looking for examples.

ConvertMUVodsTOSTRMFilesWebUI.jpg.a7c30ff4e1e970bb7eac4b06fae13c24.jpg

Then it is ran as a scheduled task, it creates the strm and downloads the logo as Poster.jpg into the movie folder with the strm file .(The path can be an url).
Its a scheduled Task so it keeps the directory updated with new content.  So I can run it daily, or weekly or whatever.. on a schedule.

ConvertMUVodsTOSTRMFilesTASK.jpg.3665e405bdfdc79263dccb1c6700c70d.jpg

Because it mine for my needs only, its pretty basic.  but i can make it better so that it can seperate TV VOD from Movie VOD.  

This is currently part of another plugin thats personal for myself, but if you want me to make this avaliable as a standalone plugin, I would need some examples though even if they dont work, just for the way they are named and formatted so that I can cover more bases on how to detect whether or not it was a VOD

It would also add the ability to remove what was no longer avaliable via the task aswell, its not there currently but its no biggie. :) 

 

 

This seems like it should be so easy...and should have me closer than ever before to getting this set up... been trying to find a way for years already. I'm adding the URL as another "TV Source", creating the "VOD" library, but I can't find the area pictured above where you specify "Local or Mapped Backup Drive Paths". What am I missing here?!

mickle026
Posted
6 hours ago, sundevil67 said:

This seems like it should be so easy...and should have me closer than ever before to getting this set up... been trying to find a way for years already. I'm adding the URL as another "TV Source", creating the "VOD" library, but I can't find the area pictured above where you specify "Local or Mapped Backup Drive Paths". What am I missing here?!

Look in this thread 

I posted a public version, that's probably what you have acquired, it's a little bit different from the example I posted here.

The web gui is similar, but allows for upto 3 m3u files.

There is also a more in-depth explanation of it.

sundevil67
Posted
13 hours ago, mickle026 said:

Look in this thread 

I posted a public version, that's probably what you have acquired, it's a little bit different from the example I posted here.

The web gui is similar, but allows for upto 3 m3u files.

There is also a more in-depth explanation of it.

Thank you! I've installed the plugin .. wondering one thing; is it supposed to automatically check the "Saving Split m3u Files" options, even if I'm just trying to work with movies? 

I tried creating a m3uFiles folder also anyway, but all it was doing is creating new directories with empty m3u files inside; no STRM files. Without specifying that directory, it just doesn't do anything. Can you tell what's going wrong just from that terrible description?

 

Screenshot 2025-02-25 at 9.18.37 AM.png

mickle026
Posted

I see the issue, i will fix it soon.

sftech13
Posted

This Python script takes your M3U playlists and converts them into .strm files, making it a lot easier to manage your digital library. It handles separate playlists for Movies, TV Shows, and Documentaries, automatically organizing everything into the right folders.

  • Multi-Source Processing: It reads through M3U files for movies, TV shows, and documentaries.
  • Dynamic Folder Organization: Automatically creates the necessary directories and sorts .strm files into them.
  • Genre Check with TMDB API (you need a key): When processing movie titles, it checks TMDB to see if a title is actually a documentary and, if so, sends it to the Documentaries folder.
  • Caching & Logging: Uses caching to skip duplicate entries and logs its actions to help you troubleshoot any issues.

 

M3U_to_Strm.py

fbrassin
Posted

Nice script.

It's working fine.

Question, if i have just one m3u file, does it recognises movies, tv show and documentaries?

sftech13
Posted (edited)
On 3/4/2025 at 1:56 AM, fbrassin said:

Nice script.

It's working fine.

Question, if i have just one m3u file, does it recognises movies, tv show and documentaries?

I've updated the script so that it now works with a single M3U file. The workflow is as follows:

  • Cache Building:
    • On the first run, the script scans your existing media directories (Movies, TV Shows, Documentaries, Animation, StandUp, etc.) and builds a cache file. (Note that this can take a few minutes depending on your library size.)
  • M3U Parsing:
    • It then parses your single M3U file against your existing VOD/Series library.
  • .strm File Creation:
    • If an entry from the M3U is not found in your local media (based on normalized titles), it creates a corresponding .strm file.
    • Additionally, if a movie is determined to be a documentary (using the TMDB API), it places the .strm file into the Documentary folder instead of the Movies folder.
  • Prevents Duplicates from being added also. 

You'll need to set a few user options (like your TMDB API key and your media directory paths) in the configuration file before running the tool. You can find all details and the latest version here:
https://github.com/sftech13/m3u2strm

Just FYI for people the full run on the initial pass took about 2 hours. Now that he cache is made it will be quick. 

 

Also it made 19480 .strm files. Time for EMBY library stress test.....LOL
 

2025-03-05 13:52:15 - INFO - Starting M3U to STRM conversion for Movies, TV Shows, and Documentaries...
2025-03-05 15:55:54 - DEBUG - Saved cache with 19480 entries
2025-03-05 15:55:54 - INFO - All .strm files have been created successfully for Emby.

 

Edited by sftech13
fbrassin
Posted
21 hours ago, sftech13 said:

I've updated the script so that it now works with a single M3U file. The workflow is as follows:

  • Cache Building:
    • On the first run, the script scans your existing media directories (Movies, TV Shows, Documentaries, Animation, StandUp, etc.) and builds a cache file. (Note that this can take a few minutes depending on your library size.)
  • M3U Parsing:
    • It then parses your single M3U file against your existing VOD/Series library.
  • .strm File Creation:
    • If an entry from the M3U is not found in your local media (based on normalized titles), it creates a corresponding .strm file.
    • Additionally, if a movie is determined to be a documentary (using the TMDB API), it places the .strm file into the Documentary folder instead of the Movies folder.
  • Prevents Duplicates from being added also. 

You'll need to set a few user options (like your TMDB API key and your media directory paths) in the configuration file before running the tool. You can find all details and the latest version here:
https://github.com/sftech13/m3u2strm

Just FYI for people the full run on the initial pass took about 2 hours. Now that he cache is made it will be quick. 

 

Also it made 19480 .strm files. Time for EMBY library stress test.....LOL
 

2025-03-05 13:52:15 - INFO - Starting M3U to STRM conversion for Movies, TV Shows, and Documentaries...
2025-03-05 15:55:54 - DEBUG - Saved cache with 19480 entries
2025-03-05 15:55:54 - INFO - All .strm files have been created successfully for Emby.

 

I don't understand something about config file.

 "output_dir": "<base output directory for STRM files>",
 
  "existing_media_dir": "<base directory for your existing media>",
 
   "movies_existing_dir": "<path to existing movies directory>",

These 3 aren't all the same?

In output dir i put the folder where to put strm files.

What should i put in existing media and what in movie existing?

Maybe is where are stored my mkv files?

sftech13
Posted
9 minutes ago, fbrassin said:

I don't understand something about config file.

 "output_dir": "<base output directory for STRM files>",
 
  "existing_media_dir": "<base directory for your existing media>",
 
   "movies_existing_dir": "<path to existing movies directory>",

These 3 aren't all the same?

In output dir i put the folder where to put strm files.

What should i put in existing media and what in movie existing?

Maybe is where are stored my mkv files?

Take a look at my config for reference. 

 

Output is where you want the .strm directory and files to go. 

Existing is your currently library of media not .strm so it can check what you have and not create duplicates. 

Movies Existing is where your existing movies media folder is. ( I should clean this part of the code up, its redundant) 

 

{
    "m3u": "/path_to_m3u",
    "cache_file": "/home/cache.json",
    "log_file": "/home/logs/M3UtoStrm.log",
    "output_dir": "/media/m3u2strm",
    "tmdb_api": "TMDB_KEY_HERE",
    "existing_media_dir": "/media/Existing",
    "existing_media_cache_file": "/home/existing_media_cache.json",
    "tv_group_keywords": [
        "ser",
        "Series"
    ],
    "doc_group_keywords": [
        "doc"
    ],
    "movie_group_keywords": [
        "vod",
        "movies"
    ],
    "movies_existing_dir": "/media/Existing/Movies",
    "tv_existing_dir": "/media/Existing/TV Shows",
    "docs_existing_dir": "/media/Existing/Documentary",
    "animation_existing_dir": "/media/Existing/Animation",
    "standup_existing_dir": "/media/Existing/StandUp",
    "dry_run": false,
    "max_workers": 5
}

 

fbrassin
Posted

OK, i'll try tonight and let you know how it goes.

  • Like 1
fbrassin
Posted

I don't know if something has changed in github, but yesterday i run the .py you uploaded here, but in Tv Show folders have been created like this:

image.png.a5fb87ed4135b6e0c80f0f9477dfedc1.png

While for Emby shoud be:

Alaska ...-> Season01-> all strm files

Am i doing something wrong?

sundevil67
Posted

I'm tempted but I think I have to wait until the plugin in the catalog can be sorted out ... the Python stuff may just be a little over my head.

sftech13
Posted (edited)
4 hours ago, fbrassin said:

I don't know if something has changed in github, but yesterday i run the .py you uploaded here, but in Tv Show folders have been created like this:

image.png.a5fb87ed4135b6e0c80f0f9477dfedc1.png

While for Emby shoud be:

Alaska ...-> Season01-> all strm files

Am i doing something wrong?

This looks like a parsing issue. Would you mind sharing the m3u show details? Not the URL just the show and episode structure. 

I may have the regex to strict 

Edited by sftech13
fbrassin
Posted
6 hours ago, sftech13 said:

This looks like a parsing issue. Would you mind sharing the m3u show details? Not the URL just the show and episode structure. 

I may have the regex to strict 

Here it is:

#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E01" tvg-logo="https://image.tmdb.org/t/p/w300/vsHmET7A8YGXH0M1ucyDOOTvpg2.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E01
http://XXX/963592.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E02" tvg-logo="https://image.tmdb.org/t/p/w300/c6NzUAnYJHAAmlk5oc1qSx7bhGh.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E02
http://XXX/327564.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E03" tvg-logo="https://image.tmdb.org/t/p/w300/dkNaIJc7zhKwXlRi2axH3b91wC9.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E03
http://XXX/327565.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E04" tvg-logo="https://image.tmdb.org/t/p/w300/iiBNCi1V5xXHpmJ4hPduMobjRlc.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E04
http://XXX/327566.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E05" tvg-logo="https://image.tmdb.org/t/p/w300/v6jehgEbKZWzwIUwZeT9Gh1L5Z7.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E05
http://XXX/327567.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E06" tvg-logo="https://image.tmdb.org/t/p/w300/qNeFcGGf82NJy1O0G6GYhh40eVI.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E06
http://XXX/327568.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E07" tvg-logo="https://image.tmdb.org/t/p/w300/f7GaFjnTL0euMbNuWf1RpFgF2Y0.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E07
http://XXX/327569.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E08" tvg-logo="https://image.tmdb.org/t/p/w300/z2L3Aw9RDmpMcruij7tODi8mGnq.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E08
http://XXX/327570.mp4

 

sftech13
Posted
9 hours ago, fbrassin said:

Here it is:

#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E01" tvg-logo="https://image.tmdb.org/t/p/w300/vsHmET7A8YGXH0M1ucyDOOTvpg2.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E01
http://XXX/963592.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E02" tvg-logo="https://image.tmdb.org/t/p/w300/c6NzUAnYJHAAmlk5oc1qSx7bhGh.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E02
http://XXX/327564.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E03" tvg-logo="https://image.tmdb.org/t/p/w300/dkNaIJc7zhKwXlRi2axH3b91wC9.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E03
http://XXX/327565.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E04" tvg-logo="https://image.tmdb.org/t/p/w300/iiBNCi1V5xXHpmJ4hPduMobjRlc.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E04
http://XXX/327566.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E05" tvg-logo="https://image.tmdb.org/t/p/w300/v6jehgEbKZWzwIUwZeT9Gh1L5Z7.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E05
http://XXX/327567.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E06" tvg-logo="https://image.tmdb.org/t/p/w300/qNeFcGGf82NJy1O0G6GYhh40eVI.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E06
http://XXX/327568.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E07" tvg-logo="https://image.tmdb.org/t/p/w300/f7GaFjnTL0euMbNuWf1RpFgF2Y0.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E07
http://XXX/327569.mp4
#EXTINF:-1 tvg-id="" tvg-name="Alaska: gli alieni sono tra noi S01 E08" tvg-logo="https://image.tmdb.org/t/p/w300/z2L3Aw9RDmpMcruij7tODi8mGnq.jpg" group-title="Serie Discovery+",Alaska: gli alieni sono tra noi S01 E08
http://XXX/327570.mp4

 

Thanks, I made an update to the regex as I suspected. 
 

r"[Ss](?:eason\s*)?(\d+)\s*[Ee]\s*(\d+)"

Can you grab the latest update and try again?

fbrassin
Posted
3 hours ago, sftech13 said:

Thanks, I made an update to the regex as I suspected. 
 

r"[Ss](?:eason\s*)?(\d+)\s*[Ee]\s*(\d+)"

Can you grab the latest update and try again?

I will try it and let you know.

Do you think i have to delete all (cache and dir) and do all from the beginning to better know how it goes?

mickle026
Posted (edited)

@sftech13Does this help?


Its in c#, a bit more involved and wont capture everything yet - its still growing - LOL, pretty sure if you wanted you could adapt it or what you need from it to python
 

static (int Season, int Episode)? ExtractSeasonEpisode(string input)
{
    // Pattern to capture season and episode details while handling various formats, including Japanese and Korean variants
    string pattern = @"(?i)" + // Enable case-insensitive matching
                     "(\\s+(S|Season|Sezon|Serie|Series|Seazon|シーズン|시즌)\\s?\\d{1,4}" + // Match season keywords (English/Japanese/Korean)
                     "[\\s._-]*(?:E|Episode|ep|e|エピソード|에피소드|화|話)[\\s]*?(\\d{1,4}))" + // Match episode keywords (English/Japanese/Korean/shortened)
                     "|(?:^|\\s)S(?<season>\\d{1,2})\\sE(?<episode>\\d{1,2})" + // Match compact SxxExx format
                     "|(?:Episode[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like 'Episode 5'
                     "|(?:エピソード[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like 'エピソード5'
                     "|(?:에피소드[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like '에피소드5'
                     "|(?:화[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like '화5'
                     "|(?:話[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like '話5'
                     "|(?<seasonOnly>\\d{1,2})\\s*-\\s*(?:Episode|エピソード|에피소드|화|話)\\s*(?<episode>\\d{1,4})"; // Match '2 - Episode/エピソード/에피소드/화/話 5'

    // Perform regex matching against the input string
    var match = Regex.Match(input, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

    if (match.Success)
    {
        int season = 0; // Initialize default season value
        int episode = 0; // Initialize default episode value

        if (match.Groups[1].Success && match.Groups[2].Success) // Match season and episode
        {
            season = int.Parse(match.Groups[1].Value);
            episode = int.Parse(match.Groups[2].Value);
        }
        else if (match.Groups["season"].Success && match.Groups["episode"].Success) // Match named groups for season and episode
        {
            season = int.Parse(match.Groups["season"].Value);
            episode = int.Parse(match.Groups["episode"].Value);
        }
        else if (match.Groups["episodeOnly"].Success) // Match standalone episode
        {
            episode = int.Parse(match.Groups["episodeOnly"].Value);
        }
        else if (match.Groups["seasonOnly"].Success && match.Groups["episode"].Success) // Match 'season only' and episode group
        {
            season = int.Parse(match.Groups["seasonOnly"].Value);
            episode = int.Parse(match.Groups["episode"].Value);
        }

        return (season, episode); // Return extracted season and episode
    }

    return null; // Return null if no match is found
}

 

Python, automatically converted - so not sure its 100%

import re

def extract_season_episode(input_string):
    """
    Extract season and episode details from an input string.
    Supports English, Japanese, and Korean terms for 'season' and 'episode.'
    """
    # Pattern to capture season and episode details while handling various formats
    pattern = r"(?i)" + \
              r"(\s+(S|Season|Sezon|Serie|Series|Seazon|シーズン|시즌)\s?\d{1,4}" + \
              r"[\s._-]*(E|Episode|ep|e|エピソード|에피소드|화|話)[\s]*?\d{1,4})" + \
              r"|(?:^|\s)S(?P<season>\d{1,2})\sE(?P<episode>\d{1,2})" + \
              r"|(?:Episode|エピソード|에피소드|화|話)[\s._-]*(?P<episode_only>\d{1,4})" + \
              r"|(?P<season_only>\d{1,2})\s*-\s*(Episode|エピソード|에피소드|화|話)\s*(?P<episode>\d{1,4})"

    # Perform regex matching
    match = re.search(pattern, input_string, flags=re.IGNORECASE)

    if match:
        season = 0  # Default season value
        episode = 0  # Default episode value

        # Match groups for season and episode
        if match.group("season") and match.group("episode"):
            season = int(match.group("season"))
            episode = int(match.group("episode"))
        elif match.group("episode_only"):
            episode = int(match.group("episode_only"))
        elif match.group("season_only") and match.group("episode"):
            season = int(match.group("season_only"))
            episode = int(match.group("episode"))

        return season, episode  # Return the extracted season and episode

    return None  # Return None if no match is found

 

Edited by mickle026
sftech13
Posted
28 minutes ago, mickle026 said:

@sftech13Does this help?


Its in c#, a bit more involved and wont capture everything yet - its still growing - LOL, pretty sure if you wanted you could adapt it or what you need from it to python
 

static (int Season, int Episode)? ExtractSeasonEpisode(string input)
{
    // Pattern to capture season and episode details while handling various formats, including Japanese and Korean variants
    string pattern = @"(?i)" + // Enable case-insensitive matching
                     "(\\s+(S|Season|Sezon|Serie|Series|Seazon|シーズン|시즌)\\s?\\d{1,4}" + // Match season keywords (English/Japanese/Korean)
                     "[\\s._-]*(?:E|Episode|ep|e|エピソード|에피소드|화|話)[\\s]*?(\\d{1,4}))" + // Match episode keywords (English/Japanese/Korean/shortened)
                     "|(?:^|\\s)S(?<season>\\d{1,2})\\sE(?<episode>\\d{1,2})" + // Match compact SxxExx format
                     "|(?:Episode[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like 'Episode 5'
                     "|(?:エピソード[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like 'エピソード5'
                     "|(?:에피소드[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like '에피소드5'
                     "|(?:화[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like '화5'
                     "|(?:話[\\s._-]*(?<episodeOnly>\\d{1,4}))" + // Match standalone episodes like '話5'
                     "|(?<seasonOnly>\\d{1,2})\\s*-\\s*(?:Episode|エピソード|에피소드|화|話)\\s*(?<episode>\\d{1,4})"; // Match '2 - Episode/エピソード/에피소드/화/話 5'

    // Perform regex matching against the input string
    var match = Regex.Match(input, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

    if (match.Success)
    {
        int season = 0; // Initialize default season value
        int episode = 0; // Initialize default episode value

        if (match.Groups[1].Success && match.Groups[2].Success) // Match season and episode
        {
            season = int.Parse(match.Groups[1].Value);
            episode = int.Parse(match.Groups[2].Value);
        }
        else if (match.Groups["season"].Success && match.Groups["episode"].Success) // Match named groups for season and episode
        {
            season = int.Parse(match.Groups["season"].Value);
            episode = int.Parse(match.Groups["episode"].Value);
        }
        else if (match.Groups["episodeOnly"].Success) // Match standalone episode
        {
            episode = int.Parse(match.Groups["episodeOnly"].Value);
        }
        else if (match.Groups["seasonOnly"].Success && match.Groups["episode"].Success) // Match 'season only' and episode group
        {
            season = int.Parse(match.Groups["seasonOnly"].Value);
            episode = int.Parse(match.Groups["episode"].Value);
        }

        return (season, episode); // Return extracted season and episode
    }

    return null; // Return null if no match is found
}

 

Python, automatically converted - so not sure its 100%

import re

def extract_season_episode(input_string):
    """
    Extract season and episode details from an input string.
    Supports English, Japanese, and Korean terms for 'season' and 'episode.'
    """
    # Pattern to capture season and episode details while handling various formats
    pattern = r"(?i)" + \
              r"(\s+(S|Season|Sezon|Serie|Series|Seazon|シーズン|시즌)\s?\d{1,4}" + \
              r"[\s._-]*(E|Episode|ep|e|エピソード|에피소드|화|話)[\s]*?\d{1,4})" + \
              r"|(?:^|\s)S(?P<season>\d{1,2})\sE(?P<episode>\d{1,2})" + \
              r"|(?:Episode|エピソード|에피소드|화|話)[\s._-]*(?P<episode_only>\d{1,4})" + \
              r"|(?P<season_only>\d{1,2})\s*-\s*(Episode|エピソード|에피소드|화|話)\s*(?P<episode>\d{1,4})"

    # Perform regex matching
    match = re.search(pattern, input_string, flags=re.IGNORECASE)

    if match:
        season = 0  # Default season value
        episode = 0  # Default episode value

        # Match groups for season and episode
        if match.group("season") and match.group("episode"):
            season = int(match.group("season"))
            episode = int(match.group("episode"))
        elif match.group("episode_only"):
            episode = int(match.group("episode_only"))
        elif match.group("season_only") and match.group("episode"):
            season = int(match.group("season_only"))
            episode = int(match.group("episode"))

        return season, episode  # Return the extracted season and episode

    return None  # Return None if no match is found

 

@mickle026 thanks I have added the robust regex to the script. 

updated repo on git. 

# New robust TV season/episode pattern Thx @mickle026
tv_pattern = re.compile(
    r"(?i)(\s+(S|Season|Sezon|Serie|Series|Seazon|シーズン|시즌)\s?\d{1,4}[\s._-]*(?:E|Episode|ep|e|エピソード|에피소드|화|話)[\s]*?(\d{1,4}))"
    r"|(?:^|\s)S(?P<season>\d{1,2})\s*E(?P<episode>\d{1,2})"
    r"|(?:Episode[\s._-]*(?P<episodeOnly>\d{1,4}))"
    r"|(?:エピソード[\s._-]*(?P<episodeOnly>\d{1,4}))"
    r"|(?:에피소드[\s._-]*(?P<episodeOnly>\d{1,4}))"
    r"|(?:화[\s._-]*(?P<episodeOnly>\d{1,4}))"
    r"|(?:話[\s._-]*(?P<episodeOnly>\d{1,4}))"
    r"|(?P<seasonOnly>\d{1,2})\s*-\s*(?:Episode|エピソード|에피소드|화|話)\s*(?P<ep>\d{1,4})",
    re.IGNORECASE
)

 

sftech13
Posted
57 minutes ago, fbrassin said:

I will try it and let you know.

Do you think i have to delete all (cache and dir) and do all from the beginning to better know how it goes?

If you want but isnt needed. I also made some changes by using asynchronous M3U Parsing so that the the parse_m3u_async function reads the entire file asynchronously, splits it into blocks based on #EXTINF, and processes each block. This minimizes memory usage and can reduce latency on large files.

fbrassin
Posted
12 hours ago, sftech13 said:

If you want but isnt needed. I also made some changes by using asynchronous M3U Parsing so that the the parse_m3u_async function reads the entire file asynchronously, splits it into blocks based on #EXTINF, and processes each block. This minimizes memory usage and can reduce latency on large files.

I've run the script but nothing has been created in Tv Shows folder.

What can i check?

mickle026
Posted

Its probably my regex, it had a fault in it.  @sftech13will probably have to update the previous submission/commit.

I fixed it here:
 

string pattern = @"(?i)(?<!\b\d{2}[\./-]\d{2}[\./-]\d{4})" + // Ignore date formats
     @"(?<!\(\d{4}-\d{4}\))" + // Ignore year ranges like (2016-2020)
     @"(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)?[\s]*?(\d{1,4})[\s._-]*(?:E|Episode|ep|e|\.|[\s._-]|エピソード|에피소드|화|話)[\s]*?(\d{1,4})" +
     @"|(?:E|Episode|ep|e|エピソード|에피소드|화|話)\.?(\d{1,4})(?:-\d{1,4})?" +
     @"|(\d{1,4})\s*-\s*Episode\s*(\d{1,4})" +
     @"|Episode\s*(\d{1,4})\s*-\s*" +
     @"|(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)\s?\d{1,4}\s?E\s?\d{1,4}" +
     @"|(?:シーズン|시즌)\s*(\d{1,4})[\s._-]*(?:エピソード|에피소드|화|話)[\s]*?(\d{1,4})";

 

python

# Regex pattern
pattern = r"(?i)(?<!\b\d{2}[\./-]\d{2}[\./-]\d{4})" + \
          r"(?<!\(\d{4}-\d{4}\))" + \
          r"(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)?[\s]*?(\d{1,4})[\s._-]*(?:E|Episode|ep|e|\.|[\s._-]|エピソード|에피소드|화|話)[\s]*?(\d{1,4})" + \
          r"|(?:E|Episode|ep|e|エピソード|에피소드|화|話)\.?(\d{1,4})(?:-\d{1,4})?" + \
          r"|(\d{1,4})\s*-\s*Episode\s*(\d{1,4})" + \
          r"|Episode\s*(\d{1,4})\s*-\s*" + \
          r"|(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)\s?\d{1,4}\s?E\s?\d{1,4}" + \
          r"|(?:シーズン|시즌)\s*(\d{1,4})[\s._-]*(?:エピソード|에피소드|화|話)[\s]*?(\d{1,4})"



 

sftech13
Posted
4 hours ago, mickle026 said:

Its probably my regex, it had a fault in it.  @sftech13will probably have to update the previous submission/commit.

I fixed it here:
 

string pattern = @"(?i)(?<!\b\d{2}[\./-]\d{2}[\./-]\d{4})" + // Ignore date formats
     @"(?<!\(\d{4}-\d{4}\))" + // Ignore year ranges like (2016-2020)
     @"(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)?[\s]*?(\d{1,4})[\s._-]*(?:E|Episode|ep|e|\.|[\s._-]|エピソード|에피소드|화|話)[\s]*?(\d{1,4})" +
     @"|(?:E|Episode|ep|e|エピソード|에피소드|화|話)\.?(\d{1,4})(?:-\d{1,4})?" +
     @"|(\d{1,4})\s*-\s*Episode\s*(\d{1,4})" +
     @"|Episode\s*(\d{1,4})\s*-\s*" +
     @"|(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)\s?\d{1,4}\s?E\s?\d{1,4}" +
     @"|(?:シーズン|시즌)\s*(\d{1,4})[\s._-]*(?:エピソード|에피소드|화|話)[\s]*?(\d{1,4})";

 

python

# Regex pattern
pattern = r"(?i)(?<!\b\d{2}[\./-]\d{2}[\./-]\d{4})" + \
          r"(?<!\(\d{4}-\d{4}\))" + \
          r"(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)?[\s]*?(\d{1,4})[\s._-]*(?:E|Episode|ep|e|\.|[\s._-]|エピソード|에피소드|화|話)[\s]*?(\d{1,4})" + \
          r"|(?:E|Episode|ep|e|エピソード|에피소드|화|話)\.?(\d{1,4})(?:-\d{1,4})?" + \
          r"|(\d{1,4})\s*-\s*Episode\s*(\d{1,4})" + \
          r"|Episode\s*(\d{1,4})\s*-\s*" + \
          r"|(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)\s?\d{1,4}\s?E\s?\d{1,4}" + \
          r"|(?:シーズン|시즌)\s*(\d{1,4})[\s._-]*(?:エピソード|에피소드|화|話)[\s]*?(\d{1,4})"



 

Thank you for the head up @mickle026 I updated the pattern. 
 

@fbrassinI have pushed the changes. Let me know how it goes. 

 

# New robust TV season/episode pattern Thx @mickle026
tv_pattern = re.compile(
    r"(?i)(?<!\b\d{2}[\./-]\d{2}[\./-]\d{4})(?<!\(\d{4}-\d{4}\))"
    r"(?:S|Season|Sezon|Serie|Series|Seazon|シーズン|시즌)?[\s]*?(\d{1,4})[\s._-]*(?:E|Episode|ep|e|\.|[\s._-]|エピソード|에피소드|화|話)[\s]*?(\d{1,4})"
    r"|(?:E|Episode|ep|e|エピソード|에피소드|화|話)\.?(\d{1,4})(?:-\d{1,4})?"
    r"|(\d{1,4})\s*-\s*Episode\s*(\d{1,4})"
    r"|Episode\s*(\d{1,4})\s*-\s*"
    r"|(?:S|Season|Sezon|Serie|Seazon|シーズン|시즌)\s?\d{1,4}\s?E\s?\d{1,4}"
    r"|(?:シーズン|시즌)\s*(\d{1,4})[\s._-]*(?:エピソード|에피소드|화|話)[\s]*?(\d{1,4})",
    re.IGNORECASE
)

 

fbrassin
Posted

I run the script again with latest update, but nothing as been created ti Tv Shows folder.

I also try to delete cache file and run the script again, but nothing in tv show.

I have all ok in movie and documentary folder

Do you need log file?

mickle026
Posted

I am continually updating my regex pattern.

The last update above is working in my emby plugin , I'm pretty sure I have updated it again since though.  I am not home much today so probably can't post the latest today.

Anyway the best thing for @sftech13to do is check it on a small sample and see if he can see why.  The question is , is it my regex or something in the translation to python such as the escape sequences in it?

I am happy to share mine , it all benefits everyone.

I will still be modifying mine as there are a few edge cases that it's still not capturing.

fbrassin
Posted

I'm testing both, this script and your plugin these days.

Both of them are great.

I like @mickle026 one because there is also the possibility to ignore words and to force entries in movies or serie.

I like @sftech13one because you can choose to import what you don't have in your media dir, so only new content.

Tnx to both for your work.

 

  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...