summaryrefslogtreecommitdiff
path: root/pkgs/servers/nextcloud/packages/apps/recognize.nix
blob: 5c799daed73f1406c08cb8ddacd3e64c921b75ce (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{
  stdenv,
  fetchurl,
  lib,
  nodejs,
  node-pre-gyp,
  node-gyp,
  python3,
  util-linux,
  ffmpeg-headless,

  # Current derivation only supports linux-x86_64 (contributions welcome, without libTensorflow builtin webassembly can be used)
  useLibTensorflow ? stdenv.isx86_64 && stdenv.isLinux,

  ncVersion,
}:
let
  latestVersionForNc = {
    "31" = {
      version = "9.0.0";
      appHash = "sha256-hhHWCzaSfV41Ysuq4WXjy63mflgEsb2qdGapHE8fuA8=";
      modelHash = "sha256-WzK9StICup/YuRcuM575DiPYHsvXGt9CRrAoBVGbXHI=";
    };
    "30" = {
      version = "8.2.0";
      appHash = "sha256-CAORqBdxNQ0x+xIVY2zI07jvsKHaa7eH0jpVuP0eSW4=";
      modelHash = "sha256-s8MQOLU490/Vr/U4GaGlbdrykOAQOKeWE5+tCzn6Dew=";
    };
    "29" = {
      version = "7.1.0";
      appHash = "sha256-qR4SrTHFAc4YWiZAsL94XcH4VZqYtkRLa0y+NdiFZus=";
      modelHash = "sha256-M/j5wVOBLR7xMVJQWDUWAzLajRUBYEzHSNBsRSBUgfM=";
    };
  };
  currentVersionInfo =
    latestVersionForNc.${ncVersion}
      or (throw "recognize currently does not support nextcloud version ${ncVersion}");
in
stdenv.mkDerivation rec {
  pname = "nextcloud-app-recognize";
  inherit (currentVersionInfo) version;

  srcs =
    [
      (fetchurl {
        inherit version;
        url = "https://github.com/nextcloud/recognize/releases/download/v${version}/recognize-${version}.tar.gz";
        hash = currentVersionInfo.appHash;
      })

      (fetchurl {
        inherit version;
        url = "https://github.com/nextcloud/recognize/archive/refs/tags/v${version}.tar.gz";
        hash = currentVersionInfo.modelHash;
      })
    ]
    ++ lib.optionals useLibTensorflow [
      (fetchurl rec {
        # For version see LIBTENSORFLOW_VERSION in https://github.com/tensorflow/tfjs/blob/master/tfjs-node/scripts/deps-constants.js
        version = "2.9.1";
        url = "https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-${version}.tar.gz";
        hash = "sha256-f1ENJUbj214QsdEZRjaJAD1YeEKJKtPJW8pRz4KCAXM=";
      })
    ];

  unpackPhase =
    ''
      # Merge the app and the models from github
      tar -xzpf "${builtins.elemAt srcs 0}" recognize;
      tar -xzpf "${builtins.elemAt srcs 1}" -C recognize --strip-components=1 recognize-${version}/models
    ''
    + lib.optionalString useLibTensorflow ''
      # Place the tensorflow lib at the right place for building
      tar -xzpf "${builtins.elemAt srcs 2}" -C recognize/node_modules/@tensorflow/tfjs-node/deps
    '';

  postPatch = ''
    # Make it clear we are not reading the node in settings
    sed -i "/'node_binary'/s:'""':'Nix Controlled':" recognize/lib/Service/SettingsService.php

    # Replace all occurrences of node (and check that we actually removed them all)
    test "$(grep "get[a-zA-Z]*('node_binary'" recognize/lib/**/*.php | wc -l)" -gt 0
    substituteInPlace recognize/lib/**/*.php \
      --replace-quiet "\$this->settingsService->getSetting('node_binary')" "'${lib.getExe nodejs}'" \
      --replace-quiet "\$this->config->getAppValueString('node_binary', '""')" "'${lib.getExe nodejs}'" \
      --replace-quiet "\$this->config->getAppValueString('node_binary')" "'${lib.getExe nodejs}'"
    test "$(grep "get[a-zA-Z]*('node_binary'" recognize/lib/**/*.php | wc -l)" -eq 0



    # Skip trying to install it... (less warnings in the log)
    sed  -i '/public function run/areturn ; //skip' recognize/lib/Migration/InstallDeps.php

    ln -s ${lib.getExe ffmpeg-headless} recognize/node_modules/ffmpeg-static/ffmpeg
  '';

  nativeBuildInputs = lib.optionals useLibTensorflow [
    nodejs
    node-pre-gyp
    node-gyp
    python3
    util-linux
  ];

  buildPhase = lib.optionalString useLibTensorflow ''
    cd recognize

    # Install tfjs dependency
    export CPPFLAGS="-I${lib.getDev nodejs}/include/node -Ideps/include"
    cd node_modules/@tensorflow/tfjs-node
    node-pre-gyp install --prefer-offline --build-from-source --nodedir=${nodejs}/include/node
    cd -

    # Test tfjs returns exit code 0
    node src/test_libtensorflow.js
    cd ..
  '';
  installPhase = ''
    approot="$(dirname $(dirname $(find -path '*/appinfo/info.xml' | head -n 1)))"
    if [ -d "$approot" ];
    then
      mv "$approot/" $out
      chmod -R a-w $out
    fi
  '';

  meta = with lib; {
    license = licenses.agpl3Only;
    maintainers = with maintainers; [ beardhatcode ];
    longDescription = ''
      Nextcloud app that does Smart media tagging and face recognition with on-premises machine learning models.
      This app goes through your media collection and adds fitting tags, automatically categorizing your photos and music.
    '';
    homepage = "https://apps.nextcloud.com/apps/recognize";
    description = "Smart media tagging for Nextcloud: recognizes faces, objects, landscapes, music genres";
    changelog = "https://github.com/nextcloud/recognize/blob/v${version}/CHANGELOG.md";
  };
}