πŸ“œ ⬆️ ⬇️

Automate subtitle uploading from * .mkv files

A couple of months ago, I had a TV with Samsung SmartTV. The device quickly became friends with the media center (the role of which is played by the Plex Media Server ) using a native application , but almost immediately a very unpleasant flaw was discovered - the lack of support for embedded subtitles in * .mkv . The prospect of removing the subtitles from each file by the handles did not please me at all, and since the torrent client is running on the same machine as the media server, it was decided to automate the processing of downloaded movies.

Under the cut there is a story about how using 30 lines of code on js of a pair of shell scripts and a plug-in for Deluge to bring * mkv-files into a viewable for TV.

Initial data


So, we have: a headless machine with Ubuntu Server 12.04LTS, Deluge 1.3.5 and Plex Media Server 0.9.7.28 with a web interface. For a start we will make a mini-TZ.

Sequencing:
  1. processing data on freshly downloaded torrent and extracting the list of * .mkv files;
  2. extract subtitles;
  3. Plex library update.

I would like to:

Deluge hook


In the basic Deluge installation there is an Execute plugin that allows you to execute an arbitrary script when adding a torrent and / or completing its download (documentation and examples can be viewed here ). We are only interested in the exact format of the arguments passed, which is not described in mans, but an example of which can be easily obtained using a test script:
#!/bin/bash echo -e "$1\n$2\n$3" >> /specshare/sample.txt 

Save the script in some public directory (I used the custom directory / specshare for this) under the name testhook.sh and give the necessary execution rights using
 sudo chmod +x testhook.sh 

Next, you need to connect the script. For remote access to Deluge, I use a GTK client, in which the sequence of actions is as follows:
  1. open Edit-Preferences-Plugins in it and put a tick in front of Execute, after which the corresponding item will appear in the Categories panel;
  2. in the Execute section, in the Event combo box, put Torrent Complete, in the Command field, specify the path to the script:
  3. click Add, OK, then restart the daemon:
     sudo service deluged restart 

')
The last step is necessary, otherwise the script simply will not be called, while correctly displayed in the settings. Now we put a small torrent on the download and in the sample.txt file we get something like:
1759d534dbe371565632ec0cccbb1579d344c5ca
Totally.Legal.Open.Source.Software.iso
/ store / distribs

The first parameter is the universal torrent identifier, which allows you to request additional information from the daemon. The second is the name of the torrent; as a rule, this is either the file name or the directory name (if there are several files in the distribution). The third is the name of the parent folder for the torrent.

Now that we know what the input parameters look like, create two files in the same directory where testhook.sh was located : extractor.sh and deluge-movie-callback.sh . The first script will be responsible for directly extracting subtitles, and we will return to it a little later, and in the second file we will enter the following:
 #!/bin/bash torrentname=$2; torrentpath=$(readlink -f "$3"); fullpath="$torrentpath/$torrentname"; echo "============================" >> /specshare/log.txt; echo "$(date +"%D %T"): $1 $2 $3" >> /specshare/log.txt; echo "$(date +"%D %T"): $fullpath" >> /specshare/log.txt; if [[ "$fullpath" != /store/films/* ]]; then echo "$(date +"%D %T"): Invalid path" >> /specshare/log.txt; exit 0; fi; echo "$(date +"%D %T"): path ok" >> /specshare/log.txt; mkvlist=$(find "$fullpath" -type f | grep .mkv); while read -r fname; do /specshare/extractor.sh "$fname" "eng,rus,unk"; done <<< "$mkvlist"; 

Nothing too complicated happens here - we glue the full file name from the $ 3 and $ 2 arguments, resolve the symlinks (if there are any), validate the path (movies and only they are downloaded to the / store / films directory, I do not need subtitles for the other video files) and for the obtained path, we request all nested mkv files. After that, for each .mkv, run extractor.sh , passing as a parameter the path and the list of ISO 639-1 codes for the required languages. β€œUnk” is our own designation for a missing language, in case it is not specified for any streams with subtitles. Script execution is logged.

A quick note about logs
Writing logs anywhere, in general, is not good, but we will sacrifice correctness for the sake of ease of access and simplicity (in my case / specshare shared via samba and with a minimum of gestures is available on the Windows desktop).


Extract subtitles


To extract the tracks with subtitles, use the mkvtoolnix package. Installation is simple:
 sudo apt-get install mkvtoolnix 

We are interested in two utilities: mkvmerge and mkvextract . The first allows you to get a list of threads in a container:
 mkvmerge -I <filename> 

Formal, the mkvinfo utility from the same package is intended for this purpose, but the output of mkvmerge is laconic and much better parseable. At the output we will get something like this:
Track ID 1: video (V_MPEG4 / ISO / AVC) [language: eng track_name: The \ sMatrix \ s1999 \ s1080p \ sBluRay \ sDD5.1 ​​\ sx264-CtrlHD display_dimensions: 1280x532 default_track: 0 forced_track: 0 packetizer: mpeg4_p10_video default_duration: 41708332 ]
Track ID 2: audio (A_AC3) [language: rus track_name: DUB-Blu-ray default_track: 1 forced_track: 0 default_duration: 32000000 audio_sampling_frequency: 48000 audio_channels: 6]
<many uninteresting audio tracks ...>
Track ID 9: audio (A_DTS) [language: eng track_name: Original default_track: 0 forced_track: 0 default_duration: 10666666 audio_sampling_frequency: 48000 audio_channels: 6]
Track ID 10: subtitles (S_TEXT / UTF8) [language: rus track_name: Sub default_track: 0 forced_track: 0]
Track ID 11: subtitles (S_TEXT / UTF8) [language: rus track_name: Sub- (by \ s \ 2 correct \ 2 \ stranslation \ sGoblin) default_track: 0 forced_track: 0]
Track ID 12: subtitles (S_TEXT / UTF8) [language: eng track_name: Sub default_track: 0 forced_track: 0]
Track ID 13: subtitles (S_TEXT / UTF8) [language: eng track_name: Sub-SDH default_track: 0 forced_track: 0]

We are interested in streams with the subtitles type and the S_TEXT / UTF8 codec, for which we need TrackID and a language code. In addition to S_TEXT / UTF8, I have met subtitles with the encoding S_HDMV / PGS, but this is a rare bird, it requires conversion to srt, and therefore we will not consider subtitles of this type. Interested offer to pay attention to the utility BDSup2Sub .

For direct extraction of the stream we use:
 mkvextract tracks <filename> <trackId>:<subname> 

The first two parameters (TrackID and the name of the container file) are pretty obvious, but with the third β€” the name for the file with subtitles β€” everything is a bit more complicated. Here it is necessary to pause for a while and become familiar with the rules for naming external subtitles in Plex .

According to the specification, the name of the subtitle should be
 ..srt, 
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .

..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .

..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
  1. ..srt,
    . , . , - , , ( ). : , - . , , .

    extractor.sh :
    #!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

    : , , //, . , capturing groups POSIX- , , , . , .

    , . - Plex.



    Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
    ; - , - PMS;
    , . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
    , , , ...

    GET-
    - PMS, UI , GET- URL . URL :
    http://<serverIP>:32400/library/sections/<sectionId>/refresh
    sectionId - PMS. , -

    - 3.

    , , deluge-movie-callback.sh -
    wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
    URL ?deep=1 ?force=1 .

    , deluge-movie-callback.sh Execute. , .

    .
    . , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
  2. ..srt,
    . , . , - , , ( ). : , - . , , .

    extractor.sh :
    #!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

    : , , //, . , capturing groups POSIX- , , , . , .

    , . - Plex.



    Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
    ; - , - PMS;
    , . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
    , , , ...

    GET-
    - PMS, UI , GET- URL . URL :
    http://<serverIP>:32400/library/sections/<sectionId>/refresh
    sectionId - PMS. , -

    - 3.

    , , deluge-movie-callback.sh -
    wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
    URL ?deep=1 ?force=1 .

    , deluge-movie-callback.sh Execute. , .

    .
    . , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
 ..srt, 
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
 ..srt, 
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .
..srt,
. , . , - , , ( ). : , - . , , .

extractor.sh :
#!/bin/bash if [[ "$1" != *.mkv ]]; then exit 0; fi; FORMAT_FULL=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\).*language:([[:alpha:]]+)"; FORMAT_SHORT=".*ID[[:space:]]([[:digit:]]+):[[:space:]]([[:alpha:]]+)[[:space:]]\((.*)\)"; baseName=${1%.mkv}; requiredLangs=$(echo "$2" | tr "," "\n"); echo "$(date +"%D %T"): $baseName" >> /specshare/log.txt; counter=0; tracks=$(mkvmerge -I "$1"); while read -r track; do echo -e "$(date +"%D %T"): $track" >> /specshare/log.txt; if [[ $track =~ $FORMAT_FULL ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; lang=${BASH_REMATCH[4]}; codec=${BASH_REMATCH[3]}; else if [[ $track =~ $FORMAT_SHORT ]]; then id=${BASH_REMATCH[1]}; tType=${BASH_REMATCH[2]}; codec=${BASH_REMATCH[3]}; lang="unk"; else id=-1; fi fi; langMatch=false; idMatch=false; typeMatch=false; codecMatch=false; shouldExtract=false; for reqLang in $requiredLangs; do [ "$reqLang" == "$lang" ] && langMatch=true; done [ "$tType" == "subtitles" ] && typeMatch=true; [ "$codec" == "S_TEXT/UTF8" ] && codecMatch=true; [ $id -ne -1 ] && idMatch=true; $langMatch && $idMatch && $typeMatch && $codecMatch && shouldExtract=true; if $shouldExtract ; then subName="$baseName.$lang.srt" if [ -f "$subName" -o "$lang" == "unk" ]; then subName="$baseName.$lang$counter.srt"; (( counter++ )); fi mkvextract tracks "$1" $id:"$subName"; fi done <<< "$tracks"

: , , //, . , capturing groups POSIX- , , , . , .

, . - Plex.



Plex Media Server Plex Media Scanner , /usr/lib/plexmediaserver/ , . , :
; - , - PMS;
, . 2 sudoers - sudo. , LD_LIBRARY_PATH ( 1) Deluge, , .
, , , ...

GET-
- PMS, UI , GET- URL . URL :
http://<serverIP>:32400/library/sections/<sectionId>/refresh
sectionId - PMS. , -

- 3.

, , deluge-movie-callback.sh -
wget -qO - http://192.168.13.1:32400/library/sections/3/refresh >> /dev/null ;
URL ?deep=1 ?force=1 .

, deluge-movie-callback.sh Execute. , .

.
. , , , - , . - , . , . Deluge , , . Label. , , , , deluged , . , c sudo su - .

Source: https://habr.com/ru/post/202870/


All Articles