Coder Social home page Coder Social logo

salvoxia / immich-folder-album-creator Goto Github PK

View Code? Open in Web Editor NEW
91.0 3.0 4.0 91 KB

Automatically create and populate albums in Immich from a folder structure in external libraries

Home Page: https://hub.docker.com/r/salvoxia/immich-folder-album-creator

Dockerfile 3.03% Shell 8.18% Python 88.79%
album folders immich

immich-folder-album-creator's People

Contributors

ciltocruz avatar salvoxia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

immich-folder-album-creator's Issues

Make parent-name optional in naming of album

Hello everyone,

first of all thank you for this great piece of software. I wouldn't be able to handle my pictures from a 15 years history without this script.

My problem is, that I sorted my pictures by year and then I included the year name in the folder.
For example:

/external_libs/photos/2020/2020 - 02 Skiing
/external_libs/photos/2020/2020 - 08 Summer at the beach 

The script now always adds the first level folder name to the album. For example, my folders are now called:

2020 2020 - 02 Skiing
2020 2020 - 08 Summer at the beach

I would appreciate it, if you could implement an option to only keep the naming of the actual folder without the inclusion of the parent, as I named them already properly.
Still I want to be able to decide the level, but just for the naming I don't want to include the parent name.

Thank you and best regards

Detects all photos but album list is empty

Am I doing something wrong? I tried it with -a '3' and -a '4' but get the same result.

username@Mac-Mini immich-folder-album-creator % python3 ./immich_auto_album.py -a '4' -s ' - ' '/Volumes/ExternalHDD/Photos/Shared Photos' 'http://10.0.0.224:2283/api' 'apikeyhere'
time=2024-04-02T16:43:31.108-07:00 level=INFO msg=Requesting all assets
time=2024-04-02T16:43:37.332-07:00 level=INFO msg=22474 photos found
time=2024-04-02T16:43:37.332-07:00 level=INFO msg=Sorting assets to corresponding albums using folder name
time=2024-04-02T16:43:37.337-07:00 level=INFO msg=0 albums identified
time=2024-04-02T16:43:37.337-07:00 level=INFO msg=Album list: []
Press Enter to continue, Ctrl+C to abort

time=2024-04-02T16:43:43.744-07:00 level=INFO msg=Listing existing albums on immich
time=2024-04-02T16:43:43.867-07:00 level=INFO msg=0 existing albums identified
time=2024-04-02T16:43:43.867-07:00 level=INFO msg=Creating albums if needed
time=2024-04-02T16:43:43.867-07:00 level=INFO msg=0 albums created
time=2024-04-02T16:43:43.867-07:00 level=INFO msg=Adding assets to albums
time=2024-04-02T16:43:43.867-07:00 level=INFO msg=Done!
username@Mac-Mini immich-folder-album-creator % 

Second Account

Hello,

I have implemented the script which is working fine for my Account.
I have now created an Account for my wife.
How can i get this script working for different immich Account in one Docker?

Thanks

Manual run from composed service

If my service is configured on the compose stack to run CRONly like:

  immich-folder-album-creator:
    container_name: immich_folder_album_creator
    image: salvoxia/immich-folder-album-creator:latest
    restart: unless-stopped
    environment:
      API_URL: http://immich_server:3001/api
      API_KEY: YQTOPW6MEY4SLPC37LyXrbtuXoULt6Hl1F9DYoePXw
      ROOT_PATH: /volume1/Photos
      CRON_EXPRESSION: "0 0 * * *"
      TZ: Europe/Paris

Is there a way to run the job manually ?

Main album unexpected name; Main album cannot be deleted

@Salvoxia thank you for such a useful tool! Much needed!

I have a scenario where the main album with an unexpected album name and which holds all photos cannot be deleted. It may just be my wrongdoing, though.

In a setup where immich is running as a docker and an external library is set as well and mapped as...

home/user/USBdrive/Photos:/usr/src/app/external
and

home/user/USBdrive/Photos
home/user/USBdrive/Photos/Family Photos
home/user/USBdrive/Photos/Family Photos/Trips
home/user/USBdrive/Photos/Family Photos/Trips/Trip 001
home/user/USBdrive/Photos/Family Photos/Trips/Trip 001
...
home/user/USBdrive/Photos/Family Photos/Trips/Trip 099

When running immich-folder-album-creator docker (Raspbian (Debian 12 bookworm)

sudo docker run --rm -e API_URL="https://website.com/api/" -e API_KEY="123" -e ROOT_PATH="/usr/src/app/external" -e ALBUM_LEVELS=3 -e LOG_LEVEL=INFO salvoxia/immich-folder-album-creator:latest /script/immich_auto_album.sh
the following albums are created

usb src
Family Photos Trips Trip 001
...
Family Photos Trips Trip 099

Albums named "Family Photos Trips Trip xxx" can be deleted (one by one) but album "usb src" cannot. A message reports it cannot be deleted, the log shows:

[Nest] 6  - 05/19/2024, 11:39:37 AM    WARN [ImmichServer] [ExpressAdapter] Content-Type doesn't match Reply body, you might need a custom ExceptionFilter for non-JSON responses
[Nest] 6  - 05/19/2024, 11:40:57 AM   ERROR [ImmichServer] [QueryFailedError: bind message has 18802 parameter formats but 0 parameters
    at PostgresQueryRunner.query (/usr/src/app/node_modules/typeorm/driver/postgres/PostgresQueryRunner.js:219:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async DeleteQueryBuilder.execute (/usr/src/app/node_modules/typeorm/query-builder/DeleteQueryBuilder.js:52:33)
    at async SubjectExecutor.executeRemoveOperations (/usr/src/app/node_modules/typeorm/persistence/SubjectExecutor.js:461:17)
    at async SubjectExecutor.execute (/usr/src/app/node_modules/typeorm/persistence/SubjectExecutor.js:104:9)
    at async EntityPersistExecutor.execute (/usr/src/app/node_modules/typeorm/persistence/EntityPersistExecutor.js:140:21)
    at async AlbumRepository.delete (/usr/src/app/dist/repositories/album.repository.js:230:9)
    at async AlbumService.delete (/usr/src/app/dist/services/album.service.js:153:9)] Failed to delete album
[Nest] 6  - 05/19/2024, 11:40:57 AM   ERROR [ImmichServer] [QueryFailedError: bind message has 18802 parameter formats but 0 parameters
    at PostgresQueryRunner.query (/usr/src/app/node_modules/typeorm/driver/postgres/PostgresQueryRunner.js:219:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async DeleteQueryBuilder.execute (/usr/src/app/node_modules/typeorm/query-builder/DeleteQueryBuilder.js:52:33)
    at async SubjectExecutor.executeRemoveOperations (/usr/src/app/node_modules/typeorm/persistence/SubjectExecutor.js:461:17)
    at async SubjectExecutor.execute (/usr/src/app/node_modules/typeorm/persistence/SubjectExecutor.js:104:9)
    at async EntityPersistExecutor.execute (/usr/src/app/node_modules/typeorm/persistence/EntityPersistExecutor.js:140:21)
    at async AlbumRepository.delete (/usr/src/app/dist/repositories/album.repository.js:230:9)
    at async AlbumService.delete (/usr/src/app/dist/services/album.service.js:153:9)] QueryFailedError: bind message has 18802 parameter formats but 0 parameters

The assumption here was setting
-e ROOT_PATH="/usr/src/app/external" as
-e ROOT_PATH="/home/user/USBdrive/Photos" would not find the photos.

If I manually remove all albums and run

sudo docker run --rm -e API_URL="https://website.com/api/" -e API_KEY="123" -e ROOT_PATH="/usr/src/app/external/Family Photos" -e ALBUM_LEVELS=3 -e LOG_LEVEL=INFO salvoxia/immich-folder-album-creator:latest /script/immich_auto_album.sh
It will still show album "usr src":

time=2024-05-19T10:40:16.713+00:00 level=INFO msg=Requesting all assets
time=2024-05-19T10:40:29.913+00:00 level=INFO msg=42169 photos found
time=2024-05-19T10:40:29.913+00:00 level=INFO msg=Sorting assets to corresponding albums using folder name
time=2024-05-19T10:40:30.098+00:00 level=INFO msg=1 albums identified
time=2024-05-19T10:40:30.098+00:00 level=INFO msg=Album list: [' usr src']
time=2024-05-19T10:40:30.098+00:00 level=INFO msg=Listing existing albums on immich
time=2024-05-19T10:40:30.393+00:00 level=INFO msg=1 existing albums identified
time=2024-05-19T10:40:30.393+00:00 level=INFO msg=Creating albums if needed
time=2024-05-19T10:40:30.393+00:00 level=INFO msg=0 albums created
time=2024-05-19T10:40:30.394+00:00 level=INFO msg=Adding assets to albums
time=2024-05-19T10:40:32.476+00:00 level=INFO msg=Done!

Is there a way to reset and begin from scratch? So that it correctly identifies the folder structure? It may have to do with setting the root path differently. Or a way to have the main album with all photos be properly named as "Family Photos" as per ROOT_PATH setting?

Thank you for any feedback in advance.

New option for Album name levels

Hi, thanks for this very promising script. I have not yet tried it, because of my following requirement for album names.

Will it be possible to add an argument for album_name_levels?
Let me explain with the following folder structure

2023
--2023-01
  --Vacation
--2023-02
--2023-03
--2023-04
  --Birdwatching
--2023-05

So I would prefer that the album names may contain up to 3 folder levels, but you can set the default value to 1 to retain existing behavior.

So with a setting of 3, my album names would look like this:
2023_2023-01
2023_2023-01_Vacation
2023_2023-02
2023_2023-03
2023_2023-04
2023_2023-04_Birdwatcing

For your kind consideration please.

[FR] Specify multiple root paths

Hi!

Do you think it would be possible to support inputting multiple root paths ?
I'm currently running multiple containers on a swarm cron planning for this.

Thanks.

Add option to name album by deepest folder only

Very nice script, saved me a lot of manual work :)

I modified it a little bit to name the albums only by the deepest folder name. My album structure is like:
2020/2020-01/2020-01-01
2020/2020-03/2020-03-27

Could be nicer but this works fine:

logging.info("Sorting assets to corresponding albums using folder name")
album_to_assets = defaultdict(list)
deepest_folders = set()

for asset in assets:
    asset_path = asset['originalPath']
    if root_path not in asset_path:
        continue
    # Chunks of the asset's path below root_path
    path_chunks = asset_path.replace(root_path, '').split('/') 
    # A single chunk means it's just the image file in no sub folder, ignore
    if len(path_chunks) == 1:
        continue
    deepest_folder = path_chunks[-2]  # Extracting the deepest folder
    deepest_folders.add(deepest_folder)
    album_to_assets[deepest_folder].append(asset['id'])

logging.info("%d albums identified", len(deepest_folders))
logging.info("Album list: %s", list(deepest_folders))
if not unattended:
    print("Press Enter to continue, Ctrl+C to abort")
    input()

Could be integrated as second option to your already implemented album level naming.

Album_levels is ignored

I set the ALBUM_LEVELS variable to 2 in the Docker container, but only one album is created.

docker-compose.yml

immich-folder-album-creator:
container_name: immich_folder_album_creator
image: salvoxia/immich-folder-album-creator:latest
restart: unless-stopped
environment:
API_URL: http://192.168.150.135:2283/api
API_KEY: API-KEY
ROOT_PATH: /usr/src/app/external
ALBUM-LEVELS: "2"
LOG_LEVEL: "DEBUG"
CRON_EXPRESSION: "*/1 * * * *"
TZ: Europe/Berlin

`time=2024-04-03T13:10:00.352+02:00 level=DEBUG msg=root_path = /usr/src/app/external
time=2024-04-03T13:10:00.352+02:00 level=DEBUG msg=root_url = http://192.168.150.135:2283/api
time=2024-04-03T13:10:00.352+02:00 level=DEBUG msg=api_key = APIKEY
time=2024-04-03T13:10:00.352+02:00 level=DEBUG msg=number_of_images_per_request = 2000
time=2024-04-03T13:10:00.353+02:00 level=DEBUG msg=number_of_assets_to_fetch_per_request = 5000
time=2024-04-03T13:10:00.353+02:00 level=DEBUG msg=unattended = True
time=2024-04-03T13:10:00.353+02:00 level=DEBUG msg=album_levels = 1
time=2024-04-03T13:10:00.353+02:00 level=DEBUG msg=album_level_separator =
time=2024-04-03T13:10:00.353+02:00 level=INFO msg=Requesting all assets
time=2024-04-03T13:10:00.355+02:00 level=DEBUG msg=Starting new HTTP connection (1): 192.168.150.135:2283
time=2024-04-03T13:10:00.377+02:00 level=DEBUG msg=http://192.168.150.135:2283 "GET /api/asset?take=5000 HTTP/1.1" 200 7304
time=2024-04-03T13:10:00.378+02:00 level=DEBUG msg=Received 6 assets with chunk 1
time=2024-04-03T13:10:00.378+02:00 level=INFO msg=6 photos found
time=2024-04-03T13:10:00.379+02:00 level=INFO msg=Sorting assets to corresponding albums using folder name
time=2024-04-03T13:10:00.379+02:00 level=INFO msg=1 albums identified
time=2024-04-03T13:10:00.379+02:00 level=INFO msg=Album list: ['Auto']
time=2024-04-03T13:10:00.379+02:00 level=INFO msg=Listing existing albums on immich
time=2024-04-03T13:10:00.380+02:00 level=DEBUG msg=Starting new HTTP connection (1): 192.168.150.135:2283
time=2024-04-03T13:10:00.398+02:00 level=DEBUG msg=http://192.168.150.135:2283 "GET /api/album HTTP/1.1" 200 941
time=2024-04-03T13:10:00.399+02:00 level=INFO msg=1 existing albums identified
time=2024-04-03T13:10:00.399+02:00 level=INFO msg=Creating albums if needed
time=2024-04-03T13:10:00.399+02:00 level=INFO msg=0 albums created
time=2024-04-03T13:10:00.399+02:00 level=INFO msg=Adding assets to albums
time=2024-04-03T13:10:00.400+02:00 level=DEBUG msg=Starting new HTTP connection (1): 192.168.150.135:2283
time=2024-04-03T13:10:00.415+02:00 level=DEBUG msg=http://192.168.150.135:2283 "PUT /api/album/APIKEY/assets HTTP/1.1" 200 493
time=2024-04-03T13:10:00.415+02:00 level=INFO msg=Done!

According to the log, however, this is not taken into account. What am I doing wrong?

My folder structure for testing is:

/usr/src/app/external
it contains the folder Auto/Opel
and Auto/Seat

Multiple import paths in external library

My photos are on a NAS (readonly NFS share) mounted in Immich.
The external album has 2 import paths:

/usr/src/app/mypics/2023/
                        2023-jan
                        2023-feb
                        2023-mar
/usr/src/app/mypics/_mobile/2023/   
                                2023-photos-anna
                                2023-photos-dj

FIRST Go to /mypics/2023 and run the script for the current folder . As expected the script generates albums

  • "2023-jan", "2023-feb" and "2023-mar"

SECOND Go to /mypics/_mobile/2023/ and run the script again for the current folder:
At this point I would expect the script to generate albums

  • "2023-photos-anna" and "2023-photos-dj"

But these are not created.

Is this code compatible with "multiple import paths" in an external library?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.