MacOS vs Linux discrepancy

All your suggestions, requests and ideas for future development
Post Reply
devster
Posts: 417
Joined: 06 Jun 2017, 22:56

MacOS vs Linux discrepancy

Post by devster »

I'm testing the recent 4.9.0 release.
I have a fairly complex format:

Code: Select all

{
  def norm = { it.replaceAll(/[`´‘’ʻ""“”]/, "'")
                 .replaceAll(/[|]/, " - ")
                 .replaceAll(/[?]/, "\uFE56")
                 .replaceAll(/[*\p{Zs}]+/, " ")
                 .replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
                 .replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }) }

  def transl = { it.transliterate("Any-Latin; NFD; NFC; Title") }
  def isLatin = { java.text.Normalizer.normalize(it, java.text.Normalizer.Form.NFD)
                                      .replaceAll(/\p{InCombiningDiacriticalMarks}+/, "") ==~ /^\p{InBasicLatin}+$/ }

  Boolean isEng = any{ audio.language.first() ==~ /en/ }{ true }
  Boolean isJpn = any{ languages.first().ISO2 ==~ /ja/ || audio.language.first() ==~ /ja/ }{ false }

  // WARNING: any db.{AniDB,TheTVDB} binding requires FileBot 4.8.6 or above
  String mainTitle = any{ db.TheTVDB.n }{ norm(n).colon(" - ").replaceTrailingBrackets() }
  String primTitle = norm(primaryTitle).colon(" - ")

  public static String surround(String self, Character left = "(", Character right = ")") {
    return left + self + right
  }

allOf
  { "Anime" }
  { allOf
      { mainTitle }
      { db.TheTVDB.y.toString().surround() }
    .join(" ") }
  {
    if (episode.special) {
      "Specials"
    } else {
      allOf
        { ["Season", db.TheTVDB.s].join(" ") }
        { if (mainTitle != primTitle) primTitle.surround("[", "]") }
        { db.TheTVDB.sy.bounds().join("-").surround() }
      .join(" ")
    }
  }
  { allOf
  	{ allOf
        { def grp = net.filebot.media.MediaDetection.releaseInfo.getReleaseGroup(fn.replaceAll(/\[.*\]$/, ""))
          (grp) ? "[$grp]" : "[$group]" }
        { mainTitle }
      .join(" ") }
    {
      if (episode.special) {
        "S$special"
      } else {
        any
          { allOf
              { db.TheTVDB.sxe }
              { db.TheTVDB.absolute.pad(2).surround() }
            .join(" ") }
          { absolute.pad(2) }
      }
    }
    { allOf
      {
        def trLang = any{ if (isJpn) "x-jat" }{ if (isEng) "eng" }{ audio.language.first() }{"eng"}
        switch (trLang) {
          case { it == "x-jat" }:
          allOf
            { norm(localize."$trLang".t).colon(", ").slash("\u2571") }
            { "[" + norm(t).colon(", ").slash("\u2571") + "]" }
          .join(" ")
          break
        case { it == "eng" }:
          norm(t).colon(", ").slash("\u2571")
          break
        default:
          norm(localize."$trLang".t).colon(", ").slash("\u2571")
        }
      }
      { tags.join(", ").replaceAll(/^/, " - ") }
      { "PT $pi" }
      { allOf
        { allOf
          { allOf
              { vf }
              { vc }
              {
                def _HDRMap = [
                  "HDR10": "HDR10",
                  "SMPTE ST 2086": "HDR10",
                  "SMPTE ST 2094 App 4": "HDR10+",
                  "Dolby Vision / SMPTE ST 2086": "Dolby Vision",
                  "Dolby Vision / HDR10": "Dolby Vision",
                  "SL-HDR1": "SL-HDR1",
                  "SL-HDR2": "SL-HDR2",
                ]
                def vid = video.first()
                if (bitdepth > 8) {
                  String _HDR
                  switch (vid) {
                    case { it.findAll { p -> p.key =~ /^HDR_/ }.size() > 0 }:
                      _HDR = any
                        { vid["HDR_Format_Commercial"] }
                        { vid["HDR_Format"] }
                        { hdr }
                        { null }
                      _HDRMap.find { k, v ->
                        k =~ _HDR
                      }?.value
                      break
                    case { it["transfer_characteristics"].findMatch(/HLG/) }:
                      "HLG"
                      break
                    case { it["transfer_characteristics"] == "PQ" && it["colour_primaries"] == "BT.2020" }:
                      "HDR"
                      break
                    default:
                      "$bitdepth-bit"
                    break
                  }
                }
              }
            .join(" ")
          }
          {
            def mCFP = [
              "FLAC": "FLAC",
              "PCM": "PCM",
              "MPEG Audio Layer 3": "MP3",
              "AAC LC": "AAC LC",
              "AAC LC SBR": "HE-AAC",
              "AAC LC SBR PS": "HE-AACv2",
              "AC-3 Dep": "E-AC-3+Dep",
              "AC-3 Blu-ray Disc Dep": "E-AC-3+Dep",
              "E-AC-3 Blu-ray Disc Dep": "E-AC-3+Dep",
              "E-AC-3 Dep": "E-AC-3+Dep",
              "E-AC-3 JOC": "E-AC-3 JOC",
              "DTS XBR": "DTS-HD HRA",
              "DTS ES": "DTS-ES Matrix",
              "DTS ES XBR": "DTS-HD HRA",
              "DTS ES XXCH XBR": "DTS-HD HRA",
              "DTS ES XXCH": "DTS-ES Discrete",
              "DTS ES XXCH XLL": "DTS-HD MA",
              "DTS XLL": "DTS-HD MA",
              "DTS XLL X": "DTS-X",
              "MLP FBA": "TrueHD",
              "MLP FBA 16-ch": "TrueHD",
              "DTS 96/24": "DTS 96-24",
            ]

            audio.collect { au ->
              String _ac = any
                            { allOf
                                { any{ au["Format/String"] }{ au["Format"] } }
                                { au["Format_Profile"] }
                                { au["Format_AdditionalFeatures"] }
                              .collect{ it.tokenize() }.flatten().unique().join(" ") }
                            { au["Format_Commercial"] }
              String _aco = any{ au["Codec_Profile"] }{ au["Format_Profile"] }{ au["Format_Commercial"] }
              def _fAtmos = any{ audio.FormatCommercial =~ /(?i)atmos/ }{ false }
              def _oAtmos = any{ audio.NumberOfDynamicObjects }{ false }
              String isAtmos = (_fAtmos || _oAtmos) ? "Atmos" : null
              String    _channels = any
                                      { au["ChannelPositions/String2"] }
                                      { au["Channel(s)_Original"] }
                                      { au["Channel(s)"] }
              String    _ch
              Object    splitCh = _channels =~ /^(?i)object.based$/ ? "Object Based" :
                                  _channels.tokenize("\\/\\.")

              String    chSimple = any{ au["Channel(s)"] }{ au["Channel(s)/String"].replaceAll("channels", "") }

              switch (splitCh) {
                case { it instanceof String }:
                  _ch = allOf{ splitCh }{ chSimple + "ch" }.join(" ")
                  break

                case { it.size > 4 }:
                  def wide = splitCh.takeRight(1)
                  Double main = splitCh.take(4)*.toDouble().inject(0, { a, b -> a + b })
                  Double sub = Double.parseDouble("0." + wide.last())
                  _ch = (main + sub).toBigDecimal().setScale(1, java.math.RoundingMode.HALF_UP).toString()
                  break

                case { it.size > 1 }:
                  Double sub = Double.parseDouble(splitCh.takeRight(2).join("."))
                  _ch = splitCh.take(2)*.toDouble().plus(sub).inject(0, { a, b -> a + b })
                              .toBigDecimal().setScale(1, java.math.RoundingMode.HALF_UP).toString()
                  break

                default:
                  _ch = splitCh.first().toDouble()
              }

              def stream = allOf
                { allOf{ _ch }{ au["NumberOfDynamicObjects"] + "obj" }.join("+") }
                { allOf{ mCFP.get(_ac, _ac) }{isAtmos}.join("+") }
                { def _lang = any{ au["Language"] }{ video.first()["Language"] }
                  net.filebot.Language.findLanguage(_lang).ISO3.upperInitial() }
              def ret = [:]
              ret.id = any{ au["StreamKindId"] }{ au["StreamKindPos"] }{ au["ID"] }
              ret.data = stream
              return ret
            }.toSorted{ it.id }.collect{ it.data }*.join(" ").join(", ") }
            { def fileURL = new URL("file:///scripts/websources.txt")
              def file = new File(fileURL.toURI())
              def websources = file.exists() ? lines(file).join("|") : null
              def isWeb = (source ==~ /WEB.*/)
              def lfr = { if (isWeb) fn.match(/($websources)\.(?i)WEB/) }
              return allOf{ lfr }{ source }.join(".") }
          .join(" - ").surround("[", "]") }
        { "[$crc32]" }
        { def ed = fn.findAll(/(?i)repack|proper/)*.upper().join(".")
          if (ed) { ".$ed" } }
        {subt}
        .join("") }
      .join(" ") }
    .join(" - ") }
  .join("/") }
which I'm using on MacOS without issues, see link > https://dsc.cloud/d38828/Screen-Recordi ... -53-34.mp4
File I'm using to test is named

[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv

which I can rename to:

Anime/Mob Psycho 100 (2016)/Season 2 [Mob Psycho 100 II] (2019)/[HorribleSubs] Mob Psycho 100 - 2x01 (13) - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv

again on MacOS.
However, when I try on Linux, this is what I get:

Code: Select all

[TEST] from [Media/Anime/Mob Psycho 100 II (2019)/[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv] to [Media/Anime/Mob Psycho 100/Season 2/[HorribleSubs] Mob Psycho 100 - 2x01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [0AE0673C].mkv]
Which is missing quite a few bits (namely mediainfo and season).

Below some sysinfo/sysenv

Code: Select all

FileBot 4.9.0 (r7234)
JNA Native: 6.1.0
MediaInfo: 19.09
p7zip: p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,32 CPUs Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz (306E4),ASM,AES-NI)
unrar: UNRAR 5.50 freeware
Chromaprint: 1.4.3
Extended Attributes: OK
Unicode Filesystem: OK
Script Bundle: 2020-03-16 (r625)
Groovy: 3.0.2
JRE: OpenJDK Runtime Environment 13.0.2
JVM: 64-bit OpenJDK 64-Bit Server VM
CPU/MEM: 32 Core / 4.3 GB Max Memory / 56 MB Used Memory
OS: Linux (amd64)
HW: Linux 6bfc367e1e42 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
STORAGE: zfs [/] @ 275 GB | zfs [/config] @ 275 GB | zfs [/scripts] @ 275 GB | ceph [/cephfs] @ 5 TB | zfs [/etc/resolv.conf] @ 275 GB | zfs [/etc/hostname] @ 275 GB | zfs [/etc/hosts] @ 275 GB
DATA: /filebot

Code: Select all

# Environment Variables #
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WEBUI_PORT: 9090
S6_LOGGING: 0
PUID: 1000
TZ: Europe/Rome
JAVA_OPTS: -Xmx4g
TERM: xterm
LANG: C.UTF-8
QBITTORRENT_VER: 1:4.2.0.99~201912180418-6819-118af03~ubuntu18.04.1
CWD: /
UMASK_SET: 002
S6_OVERLAY_VER: 1.22.1.0
PWD: /
FILEBOT_VER: 4.9.0
_: /usr/bin/filebot
S6_SERVICES_GRACETIME: 0
XDG_DATA_HOME: /config
XDG_CONFIG_HOME: /config
FILEBOT_OPTS: -Dapplication.deployment=docker -Dapplication.cache=/filebot/cache -Dapplication.dir=/filebot -Djava.io.tmpdir=/tmp/filebot -Djava.library.path=/usr/lib/x86_64-linux-gnu -Djna.library.path=/usr/lib/x86_64-linux-gnu -Dnet.filebot.archive.extractor=ShellExecutables -Dnet.filebot.AcoustID.fpcalc=/usr/bin/fpcalc -Dnet.filebot.license=/filebot/license.txt -Dnet.filebot.util.prefs.file=/filebot/prefs.properties -Duser.home=/filebot
HOSTNAME: 6bfc367e1e42
PGID: 1000
OUT_DIR: /cephfs
LS_COLORS: rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
HOME: /config
SHLVL: 1

# Java System Properties #
java.specification.version: 13
sun.jnu.encoding: UTF-8
java.class.path: /usr/share/filebot/jar/filebot.jar
net.filebot.AcoustID.fpcalc: /usr/bin/fpcalc
java.vm.vendor: Oracle Corporation
grape.root: /filebot/grape
useExtendedFileAttributes: true
jna.library.path: /usr/lib/x86_64-linux-gnu
sun.arch.data.model: 64
net.filebot.archive.extractor: ShellExecutables
java.vendor.url: https://java.oracle.com/
jna.nounpack: true
user.timezone: Europe/Rome
java.vm.specification.version: 13
os.name: Linux
sun.net.client.defaultReadTimeout: 60000
jna.boot.library.path: /usr/share/filebot/lib
sun.java.launcher: SUN_STANDARD
sun.boot.library.path: /usr/share/filebot/jre/lib
sun.java.command: /usr/share/filebot/jar/filebot.jar -script fn:sysenv
jdk.debug: release
useGVFS: true
sun.cpu.endian: little
user.home: /filebot
user.language: en
java.specification.vendor: Oracle Corporation
jdk.module.path: /usr/share/filebot/jre/ext/modules/lib
java.version.date: 2020-01-14
java.home: /usr/share/filebot/jre
file.separator: /
java.vm.compressedOopsMode: Zero based
line.separator:

unixfs: false
useCreationDate: false
prism.order: sw
java.vm.specification.vendor: Oracle Corporation
java.specification.name: Java Platform API Specification
application.cache: /filebot/cache
net.filebot.UserFiles.fileChooser: JavaFX
http.agent: FileBot/4.9.0
net.filebot.theme: Darcula
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
java.runtime.version: 13.0.2+8
user.name: root
sun.net.client.defaultConnectTimeout: 10000
java.net.useSystemProxies: true
net.filebot.license: /filebot/license.txt
path.separator: :
jna.nosys: true
os.version: 4.15.0-72-generic
java.runtime.name: OpenJDK Runtime Environment
file.encoding: UTF-8
java.vm.name: OpenJDK 64-Bit Server VM
java.vendor.url.bug: https://bugreport.java.com/bugreport/
java.io.tmpdir: /tmp/filebot
swing.crossplatformlaf: javax.swing.plaf.nimbus.NimbusLookAndFeel
java.version: 13.0.2
user.dir: /
net.filebot.util.prefs.file: /filebot/prefs.properties
os.arch: amd64
java.vm.specification.name: Java Virtual Machine Specification
net.filebot.gio.GVFS: /gvfs
application.deployment: docker
java.library.path: /usr/lib/x86_64-linux-gnu
java.vm.info: mixed mode, sharing
java.vendor: Oracle Corporation
java.vm.version: 13.0.2+8
application.dir: /filebot
sun.io.unicode.encoding: UnicodeLittle
org.apache.commons.logging.Log: org.apache.commons.logging.impl.NoOpLog
java.class.version: 57.0

# Arguments #
args[0] = -script
args[1] = fn:sysenv

Done ヾ(@⌒ー⌒@)ノ
This behaviour can be replicated with the reference rednoah/filebot container launched as follows:

Code: Select all

$ docker run -it --rm -v /cephfs:/cephfs:ro -v /srv/pv/scripts:/scripts:ro --entrypoint bash rednoah/filebot
# apt-key adv --fetch-keys https://raw.githubusercontent.com/filebot/plugins/master/gpg/maintainer.pub && \
    echo "deb [arch=amd64] https://get.filebot.net/deb/ stable main" > /etc/apt/sources.list.d/filebot.list && \
    apt-get update -q && \
    DEBIAN_FRONTEND=noninteractive \
    apt-get install -q -y --no-install-recommends \
        filebot
# filebot -version
FileBot 4.9.0 (r7234) / OpenJDK Runtime Environment 13.0.2 / Linux 4.15.0-72-generic (amd64)
# /usr/bin/filebot -script fn:amc --action test --output /cephfs/Media --conflict skip -non-strict --log-file amc.log --def ut_label=anime --def @/scripts/notify.txt --def movieFormat=@/scripts/movieFormat.groovy --def seriesFormat=@/scripts/seriesFormat.groovy --def animeFormat=@/scripts/animeFormat.groovy /cephfs/Media/Anime/Mob\ Psycho\ 100\ *

...

[TEST] from [/cephfs/Media/Anime/Mob Psycho 100 II (2019)/[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv] to [/cephfs/Media/Anime/Mob Psycho 100/Season 2/[HorribleSubs] Mob Psycho 100 - 2x01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [0AE0673C].mkv]
...
I only work in black and sometimes very, very dark grey. (Batman)
User avatar
rednoah
The Source
Posts: 22998
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MacOS vs Linux discrepancy

Post by rednoah »

Which specific line of code doesn't work as expected? Which specific binding works differently?


EDIT:

Your allOf(...) calls will catch and ignore errors, so will the outermost {...} but if you create a simple format, that yields no value at all if things fail, then FileBot will let last error bubble up so you can see it:

Code: Select all

filebot -mediainfo *.mkv --format "{media}"
Expression yields empty value: Binding "media": Failed to read media info: net.filebot.mediainfo.MediaInfoException: Invalid media file: avatar.mkv
:idea: Please read the FAQ and How to Request Help.
devster
Posts: 417
Joined: 06 Jun 2017, 22:56

Re: MacOS vs Linux discrepancy

Post by devster »

I can only guess which ones don't work as they don't throw errors on MacOS, neither individually nor using the entire format.
What is missing is the following:

Code: Select all

{
	def norm = { it.replaceAll(/[`´‘’ʻ""“”]/, "'")
		.replaceAll(/[|]/, " - ")
		.replaceAll(/[?]/, "\uFE56")
		.replaceAll(/[*\p{Zs}]+/, " ")
		.replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
		.replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }) }

String mainTitle = any{ db.TheTVDB.n }{ norm(n).colon(" - ").replaceTrailingBrackets() }
String primTitle = norm(primaryTitle).colon(" - ")

	if (episode.special) {
		"Specials"
	} else {
		allOf
			{ ["Season", db.TheTVDB.s].join(" ") }
			{ if (mainTitle != primTitle) primTitle.surround("[", "]") }
			{ db.TheTVDB.sy.bounds().join("-").surround() }
		.join(" ")
	}
}
https://dsc.cloud/d38828/Screen-Shot-20 ... -02.77.png on MacOS which yields an empty value on Linux.

Code: Select all

/usr/bin/filebot -script fn:amc --action test --output /cephfs/Media --conflict skip -non-strict --log-file amc.log --def ut_label=anime --def animeFormat=@/volume1/test.groovy /cephfs/Media/Anime/Mob\ Psycho\ 100\ II\ \(2019\)/\[HorribleSubs\]\ Mob\ Psycho\ 100\ II\ -\ EP01\ -\ Biribiri\,\ Dareka\ ga\ Mite\ Iru\ \[Ripped\ Apart\,\ Someone\ Is\ Watching\]\ \[720p\ x264\ -\ 2.0\ AAC\ LC\ Jpn\]\[0AE0673C\].mkv
Locking /data/.filebot/logs/amc.log
Run script [fn:amc] at [Wed Mar 18 08:32:16 GMT 2020]
Parameter: ut_label = anime
Parameter: animeFormat = {
	def norm = { it.replaceAll(/[`´‘’ʻ""“”]/, "'")
		.replaceAll(/[|]/, " - ")
		.replaceAll(/[?]/, "\uFE56")
		.replaceAll(/[*\p{Zs}]+/, " ")
		.replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
		.replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }) }

	String mainTitle = any{ db.TheTVDB.n }{ norm(n).colon(" - ").replaceTrailingBrackets() }
	String primTitle = norm(primaryTitle).colon(" - ")

	if (episode.special) {
		"Specials"
	} else {
		allOf
			{ ["Season", db.TheTVDB.s].join(" ") }
			{ if (mainTitle != primTitle) primTitle.surround("[", "]") }
			{ db.TheTVDB.sy.bounds().join("-").surround() }
		.join(" ")
	}
}
Argument[0]: /cephfs/Media/Anime/Mob Psycho 100 II (2019)/[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv
LicenseError: UNREGISTERED
Input: /cephfs/Media/Anime/Mob Psycho 100 II (2019)/[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv
xattr: [[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv] => [Mob Psycho 100 II - 01 - Ripped Apart: Someone Is Watching]
Group: [Anime:true] => [[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv]
Mar 18, 2020 8:32:17 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
Rename episodes using [AniDB]
Auto-detected query: [Mob Psycho 100 II]
Fetching episode data for [Mob Psycho 100]
Fetching episode data for [Mob Psycho 100 II]
Fetching episode data for [Mob Psycho 100 Reigen: Shirarezaru Kiseki no Reinouryokusha]
SuppressedThrowables: Expression yields empty value
Finished without processing any files
Abort (×_×)
Second bit is:

Code: Select all

{
	if (episode.special) {
		"S$special"
	} else {
		any
		{
			allOf
				{ db.TheTVDB.sxe }
				{ db.TheTVDB.absolute.pad(2).surround() }
			.join(" ")
		}
		{ absolute.pad(2) }
	}
}
which returns 2x01 (13) on MacOS and only 01 on Linux.
And finally the entire section of video/audio info from MediaInfo is correctly returned on MacOS, but missing in Linux. I wasn't able to narrow down why.
Also, does FileBot now have a "surround" function?

EDIT:

Code: Select all

{
	/**
	* Surrounds a string with specified characters, uses "(" and ")" by default.
	*
	* e.g assert "Doctor Who".surround() == "(Doctor Who)"
	*
	* @param  left  Character used on the left of the string, "(" by default
	* @param  right Character used on the right of the string, ")" by default
	* @return       String surrounded by the specified Characters
	* @since  4.8.6
	*/
	public static String surround(String self, Character left = "(", Character right = ")") {
		return left + self + right
	}

	allOf
		{"Anime"}
		{ allOf
		  	{ primaryTitle }
			{ allOf
				{t}
				{ allOf
					{ allOf
						{ // Video
							allOf
							{ vf }
							{ vc }
							{
								def _HDRMap = [
									"HDR10": "HDR10",
									"SMPTE ST 2086": "HDR10",
									"SMPTE ST 2094 App 4": "HDR10+",
									"Dolby Vision / SMPTE ST 2086": "Dolby Vision",
									"Dolby Vision / HDR10": "Dolby Vision",
									"SL-HDR1": "SL-HDR1",
									"SL-HDR2": "SL-HDR2",
								]
								def vid = video.first()
								if (bitdepth > 8) {
									String _HDR
									switch (vid) {
									case { it.findAll { p -> p.key =~ /^HDR_/ }.size() > 0 }:
										_HDR = any
										{ vid["HDR_Format_Commercial"] }
										{ vid["HDR_Format"] }
										{ hdr }
										{ null }
										_HDRMap.find { k, v ->
										k =~ _HDR
										}?.value
										break
									case { it["transfer_characteristics"].findMatch(/HLG/) }:
										"HLG"
										break
									case { it["transfer_characteristics"] == "PQ" && it["colour_primaries"] == "BT.2020" }:
										"HDR"
										break
									default:
										"$bitdepth-bit"
										break
									}
								}
							}
							.join(" ")
						}
						{ // Audio
							def mCFP = [
								"FLAC": "FLAC",
								"PCM": "PCM",
								"MPEG Audio Layer 3": "MP3",
								"AAC LC": "AAC LC",
								"AAC LC SBR": "HE-AAC", // HE-AACv1
								"AAC LC SBR PS": "HE-AACv2",
								"AC-3 Dep": "E-AC-3+Dep",
								"AC-3 Blu-ray Disc Dep": "E-AC-3+Dep",
								"E-AC-3 Blu-ray Disc Dep": "E-AC-3+Dep",
								"E-AC-3 Dep": "E-AC-3+Dep",
								"E-AC-3 JOC": "E-AC-3 JOC",
								"DTS XBR": "DTS-HD HRA", // needs review
								"DTS ES": "DTS-ES Matrix",
								"DTS ES XBR": "DTS-HD HRA",
								"DTS ES XXCH XBR": "DTS-HD HRA", // needs review
								"DTS ES XXCH": "DTS-ES Discrete",
								"DTS ES XXCH XLL": "DTS-HD MA", // needs review
								"DTS XLL": "DTS-HD MA",
								/* "DTS XLL X": "DTS\u02D0X", // IPA triangular colon */
								"DTS XLL X": "DTS-X",
								"MLP FBA": "TrueHD",
								"MLP FBA 16-ch": "TrueHD",
								"DTS 96/24": "DTS 96-24", // needs review
							]

							audio.collect { au ->
								String _ac = any
											{ allOf
												{ any{ au["Format/String"] }{ au["Format"] } }
												{ au["Format_Profile"] }
												{ au["Format_AdditionalFeatures"] }
												.collect{ it.tokenize() }.flatten().unique().join(" ") }
											{ au["Format_Commercial"] }
								String _aco = any{ au["Codec_Profile"] }{ au["Format_Profile"] }{ au["Format_Commercial"] }
								def _fAtmos = any{ audio.FormatCommercial =~ /(?i)atmos/ }{ false }
								def _oAtmos = any{ audio.NumberOfDynamicObjects }{ false }
								String isAtmos = (_fAtmos || _oAtmos) ? "Atmos" : null
								String    _channels = any{ au["ChannelPositions/String2"] }{ au["Channel(s)_Original"] }{ au["Channel(s)"] }
								String    _ch
								Object    splitCh = _channels =~ /^(?i)object.based$/ ? "Object Based" :
													_channels.tokenize("\\/\\.")
								String    chSimple = any{ au["Channel(s)"] }{ au["Channel(s)/String"].replaceAll("channels", "") }

								switch (splitCh) {
								case { it instanceof String }:
									_ch = allOf{ splitCh }{ chSimple + "ch" }.join(" ")
									break
								case { it.size > 4 }:
									def wide = splitCh.takeRight(1)
									Double main = splitCh.take(4)*.toDouble().inject(0, { a, b -> a + b })
									Double sub = Double.parseDouble("0." + wide.last())
									_ch = (main + sub).toBigDecimal().setScale(1, java.math.RoundingMode.HALF_UP).toString()
									break
								case { it.size > 1 }:
									Double sub = Double.parseDouble(splitCh.takeRight(2).join("."))
									_ch = splitCh.take(2)*.toDouble().plus(sub).inject(0, { a, b -> a + b })
												.toBigDecimal().setScale(1, java.math.RoundingMode.HALF_UP).toString()
									break
								default:
									_ch = splitCh.first().toDouble()
								}

								def stream = allOf
								{ allOf{ _ch }{ au["NumberOfDynamicObjects"] + "obj" }.join("+") }
								{ allOf{ mCFP.get(_ac, _ac) }{isAtmos}.join("+") }
								{ def _lang = any{ au["Language"] }{ video.first()["Language"] }
									net.filebot.Language.findLanguage(_lang).ISO3.upperInitial() }
								def ret = [:]
								ret.id = any{ au["StreamKindId"] }{ au["StreamKindPos"] }{ au["ID"] }
								ret.data = stream
								return ret
							}.toSorted{ it.id }.collect{ it.data }*.join(" ").join(", ")
						}
						{
							def fileURL = new URL("file:///scripts/websources.txt")
							def file = new File(fileURL.toURI())
							def websources = file.exists() ? lines(file).join("|") : null
							def isWeb = (source ==~ /WEB.*/)
							def lfr = { if (isWeb) fn.match(/($websources)\.(?i)WEB/) }
							return allOf{ lfr }{ source }.join(".")
						}
						.join(" - ").surround("[", "]")
					}
					{ "[$crc32]" }
				.join("")
			}.join(" ")
		}.join(" - ")
	}.join("/")
}
The snippet above returns

Code: Select all

Anime/Mob Psycho 100 II - Ripped Apart: Someone Is Watching [720p x264 - 2.0 AAC LC Jpn][0AE0673C]
on MacOS but

Code: Select all

[TEST] from [/cephfs/Media/Anime/Mob Psycho 100 II (2019)/[HorribleSubs] Mob Psycho 100 II - EP01 - Biribiri, Dareka ga Mite Iru [Ripped Apart, Someone Is Watching] [720p x264 - 2.0 AAC LC Jpn][0AE0673C].mkv] to [/cephfs/Media/Anime/Mob Psycho 100 II - Ripped Apart Someone Is Watching [0AE0673C].mkv]
on Linux.
Last edited by devster on 18 Mar 2020, 09:28, edited 1 time in total.
I only work in black and sometimes very, very dark grey. (Batman)
User avatar
rednoah
The Source
Posts: 22998
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MacOS vs Linux discrepancy

Post by rednoah »

Sorry, but it's down to divide & conquer, and you can do that yourself, because I don't have a magic shortcut myself either. ;)


You can test your assumptions as explained above:
rednoah wrote: 18 Mar 2020, 06:53 Your allOf(...) calls will catch and ignore errors, so will the outermost {...} but if you create a simple format, that yields no value at all if things fail, then FileBot will let last error bubble up so you can see it:

Code: Select all

filebot -mediainfo *.mkv --format "{media}"
Expression yields empty value: Binding "media": Failed to read media info: net.filebot.mediainfo.MediaInfoException: Invalid media file: avatar.mkv
I shall elaborate on my debugging advice... that you'll want to apply within the context of your Linux container because that's where it doesn't work...


1.
Create an xattr-tagged test file:

Code: Select all

filebot -rename *.mp4 -non-strict --log INFO
[MOVE] from [Alias.1x01.mp4] to [Alias - 1x01 - Truth Be Told.mp4]

2.
Fast trial & error until you narrow down on the broken binding and it's error message:

Code: Select all

filebot -mediainfo *.mp4 --format "{db.AniDB.n}"
Expression yields empty value: Binding "AniDB": Mapping not found
:idea: Please read the FAQ and How to Request Help.
devster
Posts: 417
Joined: 06 Jun 2017, 22:56

Re: MacOS vs Linux discrepancy

Post by devster »

It doesn't seem like any of the bindings are undefined, it's the combination that fails.
This was the problematic bit:

Code: Select all

{
	public static String surround(String self, Character left = "(", Character right = ")") {
		return left + self + right
	}
	n.surround()
}
which fails on Linux:

Code: Select all

No signature of method: java.lang.String.surround() is applicable for argument types: () values: []
but not on MacOS (here).
I replaced the above function with:

Code: Select all

	String.metaClass.surround { l = "(", r = ")" ->
		l + delegate + r
	}
/code]
which seems to work on Linux.
I only work in black and sometimes very, very dark grey. (Batman)
User avatar
rednoah
The Source
Posts: 22998
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MacOS vs Linux discrepancy

Post by rednoah »

This shouldn't work, and it doesn't work:

Code: Select all

public static String surround(String self, Character left = "(", Character right = ")") {
	return left + self + right
}
n.surround()
:idea: I can only imagine we added String.surround() for the lolz in the core at some point in time, but then removed it again because it wasn't all that useful, and you somehow ended up using a specific revision where String.surround() is pre-defined by FileBot?


This should work, and does work, as this is how you add extension methods in Groovy:

Code: Select all

String.metaClass.surround = { l = "(", r = ")" ->
	l + delegate + r
}
n.surround()
:idea: Please read the FAQ and How to Request Help.
Post Reply