Skip to content

Feed problem, some videos do not show up #1130

Open

Description

@EsmailELBoBDev2

Official Instance

Describe the bug

I self host piped.esmailelbob.xyz and I noticed videos from channels I subbed to in invidious show up and takes so long to show up in piped

To Reproduce

sub to some channels
take channels file
add it to both invidious and piped

Expected behavior

videos show up in my feed when some channel upload a video

Logs/Errors

hmm, not sure what to add here

Browser, and OS with Version.

No response

Additional context

No response

Activity

  1. FireMasterK commented on Jun 27, 2022

    @FireMasterK
    Member

    Do you have a list of channel IDs that are affected by this bug?

    I can check their pubsub subscription status then at https://pubsubhubbub.appspot.com/

  2. EsmailELBoBDev2 commented on Jun 28, 2022

    @EsmailELBoBDev2
    Author

    I can give you the sub file...
    subscriptions.json.txt (had ti change it to .txt for github)

    but I noticed something weird, I had problem with my instance I think it was problem with the database, while piped worked okay the login page did not work (pressing on login button did nothing) till I restarted the docker image so I assume it's problem in my own instance, somehow fetchers do not run right?

  3. FireMasterK commented on Jul 2, 2022

    @FireMasterK
    Member

    This should be fixed with TeamPiped/Piped-Backend@3a00940, let me know if it is not.

  4. azR-103 commented on Jul 2, 2022

    @azR-103

    This should be fixed with TeamPiped/Piped-Backend@3a00940, let me know if it is not.

    Still have same issue, not all channel feed are being loaded, although i dont have this issue on this custom instance.

    https://pipedus.palash.dev

  5. FireMasterK commented on Jul 2, 2022

    @FireMasterK
    Member

    Still have same issue, not all channel feed are being loaded

    Only new videos uploaded from 6 hours back would be updated in the feed, this is due to the nature of how PubSub works.

    Let me know if this happens on new uploads from now.

  6. EsmailELBoBDev2 commented on Jul 3, 2022

    @EsmailELBoBDev2
    Author

    @FireMasterK out of context issue, I noticed piped instance and login (I guess db) sometimes disconnect and I can't login without restart the whole instance so do I need to restart it every hour like invidious?

    about feed because what happened, my sync stopped 3 days ago and now I'm waiting it to pull new videos and tell you it worked or no

  7. EsmailELBoBDev2 commented on Jul 3, 2022

    @EsmailELBoBDev2
    Author

    I have to visit each channel to get new videos in my feed, weird behavior

    Is there a command or way to force it to fetch updates from yt?

  8. EsmailELBoBDev2 commented on Jul 3, 2022

    @EsmailELBoBDev2
    Author

    still do not work, as you see in these pics, in freetube it detected it but in piped I had to visit the channel to make it appear in my feed

    Screenshot_20220704_011532
    Screenshot_20220704_011559
    Screenshot_20220704_011519

  9. FireMasterK commented on Jul 19, 2022

    @FireMasterK
    Member

    Is there any logs that you can provide? run docker-compose logs piped-backend
    The pubsub debug shows that there has been no attempts to subscribe to feed updated for over a month (!!!)
    Could you also provide you instance's config.properties file? Just ensure to redact any database information

    See: https://pubsubhubbub.appspot.com/subscription-details?hub.callback=https%3A%2F%2Fpipedapi.esmailelbob.xyz%2Fwebhooks%2Fpubsub&hub.topic=https%3A%2F%2Fwww.youtube.com%2Fxml%2Ffeeds%2Fvideos.xml%3Fchannel_id%3DUCadoKaQadkmNZg-MymcKWqg&hub.secret=

  10. EsmailELBoBDev2 commented on Jul 20, 2022

    @EsmailELBoBDev2
    Author

    Im away from my pc so excuse my werid english

    Umm weidly enoguh, i get ERROR: No such service: piped-backend so hmmm

    And my config file

    # The port to Listen on.
    PORT: 8080
    
    # The number of workers to use for the server
    HTTP_WORKERS: 2
    
    # Proxy
    PROXY_PART: https://pipedproxy.esmailelbob.xyz
    
    # Outgoing HTTP Proxy - eg: 127.0.0.1:8118
    #HTTP_PROXY: 127.0.0.1:8118
    
    # Captcha Parameters
    CAPTCHA_BASE_URL: https://api.capmonster.cloud/
    CAPTCHA_API_KEY: INSERT_HERE
    
    # Public API URL
    API_URL: https://pipedapi.esmailelbob.xyz
    
    # Public Frontend URL
    FRONTEND_URL: https://piped.esmailelbob.xyz
    
    # Enable haveibeenpwned compromised password API
    COMPROMISED_PASSWORD_CHECK: false
    
    # Disable Registration
    DISABLE_REGISTRATION: true
    
    # Feed Retention Time in Days
    FEED_RETENTION: 30
    
    # Hibernate properties
    hibernate.connection.url: jdbc:postgresql://postgres:5432/piped
    hibernate.connection.driver_class: org.postgresql.Driver
    hibernate.dialect: org.hibernate.dialect.PostgreSQL10Dialect
    hibernate.connection.username: piped
    hibernate.connection.password: donotchangeme
    
  11. FireMasterK commented on Jul 21, 2022

    @FireMasterK
    Member

    Umm weidly enoguh, i get ERROR: No such service: piped-backend so hmmm

    Try copying the name of the container from docker ps and replace it in the docker logs command.

  12. EsmailELBoBDev2 commented on Jul 21, 2022

    @EsmailELBoBDev2
    Author

    Hmm, i have piped backend running but i cant access its logs, it throws same error

  13. FireMasterK commented on Jul 21, 2022

    @FireMasterK
    Member

    Nvm, you have to run docker logs piped-backend, not docker-compose, my bad!

  14. EsmailELBoBDev2 commented on Jul 21, 2022

    @EsmailELBoBDev2
    Author

    Ohhhhh 😂

    Amyways i cant provide logs as im on phone and cant copy logs and when i send them to commandline pastebin it sends different output

  15. 68 remaining items

  16. tron1point0 commented on Mar 20, 2024

    @tron1point0

    Then you can drop the -s ("silent") flag from the curl command so it shows a progress indicator, like so:

    $ docker exec piped_postgres_1 psql -Upiped -dpiped -qtAc "SELECT DISTINCT(channel) FROM users_subscribed" | xargs -I\{} curl -k -o /dev/null 'https://[...redacted...]/channel/{}'
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  2607  100  2607    0     0   166k      0 --:--:-- --:--:-- --:--:--  181k
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  2607  100  2607    0     0   215k      0 --:--:-- --:--:-- --:--:--  231k
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    ...
  17. pinned this issue on Jan 7, 2025
  18. IngwiePhoenix commented on Jan 7, 2025

    @IngwiePhoenix

    I ran the script above (albeit modified, I use k3s) and the feed still is not updated.

    Any other way I can solve this?

    # kubectl exec -n postgres pods/default-cluster-1 -c postgres -- psql -Upostgres -d piped -qtAc "SELECT DISTINCT(channel) FROM users_subscribed" | wc -l
    768
    

    This number also shows up in the logs:

    Jan 06, 2025 8:26:23 PM liquibase.database
    INFO: Set default schema name to public
    Jan 06, 2025 8:26:24 PM liquibase.changelog
    INFO: Reading from public.databasechangelog
    Database is up to date, no changesets to execute
    Jan 06, 2025 8:26:24 PM liquibase.changelog
    INFO: Reading from public.databasechangelog
    
    UPDATE SUMMARY
    Run:                          0
    Previously run:               3
    Filtered out:                 1
    -------------------------------
    Total change sets:            4
    
    
    FILTERED CHANGE SETS SUMMARY
    DBMS mismatch:                1
    
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: UPDATE SUMMARY
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: Run:                          0
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: Previously run:               3
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: Filtered out:                 1
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: -------------------------------
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: Total change sets:            4
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: FILTERED CHANGE SETS SUMMARY
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: DBMS mismatch:                1
    Jan 06, 2025 8:26:24 PM liquibase.util
    INFO: Update summary generated
    Jan 06, 2025 8:26:24 PM liquibase.lockservice
    INFO: Successfully released change log lock
    Jan 06, 2025 8:26:24 PM liquibase.command
    INFO: Command execution complete
    ThrottlingCache: 0 entries
    SLF4J: No SLF4J providers were found.
    SLF4J: Defaulting to no-operation (NOP) logger implementation
    SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
    Jan 06, 2025 8:26:25 PM org.hibernate.Version logVersion
    INFO: HHH000412: Hibernate ORM core version [WORKING]
    Jan 06, 2025 8:26:26 PM org.hibernate.cache.internal.RegionFactoryInitiator initiateService
    INFO: HHH000026: Second-level cache disabled
    Logged in as user: null
    Room ID: !CfXSiQMnWTEPfnBNuK:matrix.org
    Filter ID: null
    Jan 06, 2025 8:26:35 PM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator initiateService
    INFO: HHH000130: Instantiating explicit connection provider: org.hibernate.hikaricp.internal.HikariCPConnectionProvider
    Jan 06, 2025 8:26:39 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl constructDialect
    WARN: HHH90000025: PostgreSQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
    Jan 06, 2025 8:26:44 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
    INFO: HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
    Database connection is ready!
    Cleanup: Removed 0 old videos
    PubSub: queue size - 763 channels
    ThrottlingCache: 0 entries
    Cleanup: Removed 0 old videos
    PubSub: queue size - 763 channels
    ThrottlingCache: 0 entries
    Cleanup: Removed 0 old videos
    (...)
    PubSub: queue size - 763 channels
    Failed to subscribe: 429
    Throttled.
    com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
     at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
            at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
            at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
            at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
            at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
            at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
            at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
            at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
    java.lang.RuntimeException: Failed to parse JSON
            at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:40)
            at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
            at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
    Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
     at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
            at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
            at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
            at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
            at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
            at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
            ... 2 more
    com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
     at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
            at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
            at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
            at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
            at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
            at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
            at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
            at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
    java.lang.RuntimeException: Failed to parse JSON
            at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:40)
            at me.kavin.piped.utils.matrix.SyncRunner.run(SyncRunner.java:97)
            at java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
    Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
     at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
            at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2648)
            at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:685)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2750)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
            at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
            at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4934)
            at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3260)
            at me.kavin.piped.utils.RequestUtils.getJsonNode(RequestUtils.java:36)
            ... 2 more
    ThrottlingCache: 0 entries
    Cleanup: Removed 0 old videos
    PubSub: queue size - 763 channels
    ThrottlingCache: 0 entries
    Cleanup: Removed 2 old videos
    ThrottlingCache: 0 entries
    (...)
    Cleanup: Removed 0 old videos
    PubSub: queue size - 764 channels
    ThrottlingCache: 0 entries
    Cleanup: Removed 0 old videos
    PubSub: queue size - 765 channels
    ThrottlingCache: 0 entries
    Cleanup: Removed 0 old videos
    ThrottlingCache: 0 entries
    Cleanup: Removed 0 old videos
    PubSub: queue size - 765 channels
    
  19. 0xF4CED commented on Jan 8, 2025

    @0xF4CED

    Here is a much improved script to do this.
    It does not hammer the API with new HTTP handshakes for every channel.
    It requests all channels in one HTTP session, and the server can decide how fast it will respond/process them.
    Also, it does not request the content of each endpoint/channel but only asks for status information, further reducing load.

    I have noticed that the piped API now takes exactly 1 second for every channel/request, which has not been the case previously.
    Is this a new rate limiting feature of piped, or is it youtubes rate limiting @FireMasterK?

    Edit: my bad, wasn't piped related.

    #!/bin/bash
    
    PIPEDAPI="https://pipedapi.example.com"
    
    curl -LIsfZkw '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' --retry 1 --config \
      <(docker exec -i piped-postgres \
        bash -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAXc \
        \"SELECT DISTINCT 'url=\"$PIPEDAPI\"/channel/' || channel FROM users_subscribed;\"") \
      >/dev/null
  20. PhrozenByte commented on Jan 9, 2025

    @PhrozenByte

    @TeamPiped Since there seems to be a stable, scriptable workaround and since a proper fix is pending for 2,5 years now, could this workaround be included in the official Docker image, so that all Piped instances benefit from it?

    The issue wasn't that serious 2,5 years ago because it only affected few videos, but since YouTube's war against adblockers and 3rd-party apps it became a permanent condition that renders Piped's subscription feature basically useless. This also affects popular dependant projects like LibreTube. Including this workaround into the official images would be very much appreciated.

  21. tron1point0 commented on Jan 9, 2025

    @tron1point0
    #!/bin/bash
    
    PIPEDAPI="https://pipedapi.example.com"
    
    SUBS=$(docker exec -i piped-postgres \
      bash -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAX -c \"select '\"$PIPEDAPI\"/channel/' || id from public.pubsub;\"")
    
    curl -LIsfZkw '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' --retry 1 $SUBS >/dev/null

    Nice! I golfed that a little differently to pass the URLs to curl via --config on STDIN because the total length of the command line is limited:

    docker exec $PIPED_CONTAINER \
        psql -U$PIPED_DB_USER -d$PIPED_DB_NAME -qtAc \
        "SELECT DISTINCT(channel) FROM users_subscribed" | \
        sed "s_^_url = $PIPED_API_URL/channel/_" | \
        curl -LIsfZ -r 1 -C - -w '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' \
        >/dev/null
    

    The sed could also be removed to make psql do all the string munging, but I find this pipeline clearer.

  22. 0xF4CED commented on Jan 11, 2025

    @0xF4CED
  23. PhrozenByte commented on Jan 11, 2025

    @PhrozenByte

    The problem is, that this is more of a hack than a proper workaround; It does not scale and is very inefficient as it queries every channel that is in the db every time, even if they have no new content for years.
    The proper way would be getting an announcement from youtube for new content like piped intended to do with pubsub.

    I'd say every workaround is a hack, that's what distinguishes it from a proper fix 😄

    The problem is that this issue persists for 2,5 years now and it seems like that nobody is either able (this includes myself), or willing to invest the time necessary to develop a proper fix, or it really can't be fixed in a meaningful way. I don't know and honestly, I don't think the reasons matter in the end. Since subscriptions is one of Piped's key features, I'd consider its breakage (and let's be honest, it's completely broken) major enough to justify a workaround until a proper fix is found and merged. That's just my IMHO though.

    So this hacky workaround is fine for your private piped instances, but for big public instances it's kind of unfeasible, unfortunately. (Especially with the 1 sec per channel rate limiting)

    Since it's a workaround, downsides - even major ones - are expected. Workarounds are temporary solutions after all. The question is whether the workaround stays feasible.

    Working with a rate limit doesn't really prevent us from applying this workaround, but only how many channels we can process in a given time. So for example, if users of a given instance have subscribed to 21,600 unique channels, feeds can only be updated four times a day max. I can only speak for myself here, but I'd definitely prefer having a feed with a 6 hour delay instead of having no working feed at all.

    I don't run a public Piped instance, so I can't really assess about how many unique channels we're talking for larger instances. For example, kavin.rocks has 421,150 registered users. It's unlikely that subscriptions don't overlap, but I guess we still end up with way too many unique channels on kavin.rocks. So, this workaround likely isn't feasible for kavin.rocks, at least not until rate limit evasion measures are taken. The two next largest instances (adminforge.de and drgns.space) have 23,367 and 13,979 registered users respectively. I can only speculate, but I would be surprised (considering what I know now, there definitely could be obstacles I just don't know, please tell me then) if we can't at least get daily updates (= 86,400 unique channels max) with this workaround on these instances. Smaller instances should be fine and allow for more than one feed update per day.

    So, let's work on improving the workaround to make it more feasible for instances of any size and ready to be included in the official Docker images.

    First we need a config option to enable/disable this workaround. This could be as simple as adding a Docker env variable. Second we can't leave calling this script up to a cronjob, because we don't know whether the number of unique channels exceeds the number of channels we can process in the cronjob's frequency. On the other hand we don't want to update channels too often. So, let's modify the script so that it runs repeatedly indefinitely and pauses if it has processed all channels before the next run is due. The frequency should be configurable, too (let's start with hourly updates).

    Here's a proof-of-concept with these two additions:

    #!/bin/bash
    PIPEDAPI="https://pipedapi.example.com"
    SUBSCRIPTIONS_WORKAROUND_ENABLED="${SUBSCRIPTIONS_WORKAROUND_ENABLED:-1}"
    SUBSCRIPTIONS_WORKAROUND_FREQUENCY="${SUBSCRIPTIONS_WORKAROUND_FREQUENCY:-3600}"
    
    if [ "$SUBSCRIPTIONS_WORKAROUND_ENABLED" == "1" ]; then
        while true; do
            sleep_until=$(($(date +%s) + SUBSCRIPTIONS_WORKAROUND_FREQUENCY))
            curl -LIsfZkw '%{stderr}%{onerror}%{urlnum}: %{url}: %{errormsg}\n' --retry 1 --config \
                <(docker exec -i piped-postgres \
                    bash -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAXc \
                    \"SELECT DISTINCT 'url=\"$PIPEDAPI\"/channel/' || channel FROM users_subscribed;\"") \
                >/dev/null
            (( $(date +%s) >= sleep_until )) || sleep $(( sleep_until - $(date +%s) ))
        done
    fi

    It still remains a rather simple workaround. That's by design, if it gets too complex it would be better to either develop a proper fix or at least include the workaround directly into Piped instead of calling Piped's API with curl. However, we're not at this point yet.

    So, let's discuss a few more possible additions. You mentioned that it doesn't make much sense to update channels that don't publish videos that frequently. I absolutely agree. A simple solution could be to actually add two workaround scripts: One frequent version that excludes channels without recent videos (that's as simple as using a different SQL query), and another less frequently running version that only updates the channels excluded by the first one. This two-tier system could also include other criteria, for example channels that don't have many subscribers could fall into the low-frequency tier, or could be excluded completely (e.g. if there's just one subscriber). The criteria could be configurable, so that admins can choose what fits their instance best. WDYT?

  24. alvv-z commented on Feb 18, 2025

    @alvv-z

    It might be possible to federate the feeds between instances to avoid excess requests if another instance has processed a channel fairly recently. Would be a much larger workaround than what @PhrozenByte suggested, however.

  25. firejoust commented on Apr 12, 2025

    @firejoust

    Unfortunately I've had no luck with the workaround on my instance. However, I made a fork based on it and it seems to do the trick for me:

    https://github.com/firejoust/Piped-Backend

    I would only recommend it for people using private instances. The instructions are provided in the README document for anyone interested.

  26. PhrozenByte commented on Apr 12, 2025

    @PhrozenByte

    @firejoust Thanks for your work! 🚀 I didn't find any open PR with your changes. How about creating one and getting some feedback about your changes? Your approach might be generally useful or at least start a discussion about how a generally useful solution might look like 👍

  27. Weidav commented on Jun 23, 2025

    @Weidav

    Unfortunately I've had no luck with the workaround on my instance. However, I made a fork based on it and it seems to do the trick for me:

    https://github.com/firejoust/Piped-Backend

    I would only recommend it for people using private instances. The instructions are provided in the README document for anyone interested.

    Works like a charm!
    Would you mind opening a PR as @PhrozenByte suggested?

  28. peetezaah commented on Jul 21, 2025

    @peetezaah

    @firejoust , @PhrozenByte and @Weidav have you found any other issues?
    Because I used the workaround and now seem to have another issue: seeking breaks the video entirely, if I jump from the beginning of a video into, for example, minute 6 of that video. It sort of reloads the video to have a much shorter length (length changes from 15 minutes to 1, for example) and sometimes I no longer can watch it other times it comes back after about a minute.

    I loaded a 15 minute video (/watch?v=u_BcMXgws6Y) and paused right at the start:
    Image
    Then I jumped into the middle of the video and the seeking/length breaks (length changed to 1:05):
    Image

    After about a minute it comes back and loads at the correct time, but that is not happening with all videos.

    Here's an example with another 15 minute video (/watch?v=9I-34I8OsPM), where the length changes to 1:02 (and then quickly to 1:01), but it does not come back and simply stops loading the video after I do that time jump.
    Image

    With the workaround I also am not able to change the resolution of a video while playing it.

  29. Weidav commented on Jul 21, 2025

    @Weidav

    @firejoust , @PhrozenByte and @Weidav have you found any other issues?

    Yes, if I use the fork, videos won't play at all in Safari due to an error. I also use yattee on mobile devices and my AppleTV and videos won't load there either.

    I tried to contact @firejoust but without luck. So might need to fork the fork and create a PR.

  30. Weidav commented on Mar 1, 2026

    @Weidav

    I created a solution using systemd that updates the feed every hour. I use Traefik, and for personal/setup reasons, I block the host machine from accessing the Piped API directly. Instead, I run the curl request from the piped-nginx container.
    Credits to @0xF4CED I took his original idea and tweaked it to fit my needs.

    Store this file in /usr/local/bin/

    update_piped_feed.sh

    #!/bin/bash
    
    PIPEDAPI="<https://pipedapi.your.com>"
    POSTGRES_CONTAINER="<piped_postgres_container_name>"
    NGINX_CONTAINER="<piped_nginx_container_name>"
    
    # 1. Get the URLs from Postgres on the host
    URLS=$(docker exec -i $POSTGRES_CONTAINER sh -c "PGPASSWORD=\$POSTGRES_PASSWORD psql -U \$POSTGRES_USER -d \$POSTGRES_DB -qtAXc \"SELECT DISTINCT '$PIPEDAPI/channel/' || channel FROM users_subscribed;\"" | tr -d '\r')
    
    # 2. Feed the URLs into a loop RUNNING INSIDE the Nginx container
    docker exec -i $NGINX_CONTAINER sh -c '
    while read -r url; do
        [ -z "$url" ] && continue
        # -m 5: give up after 5 seconds if the site is dead
        # -s: silent mode
        # -o /dev/null: dont print the 500 error body, just the code
        curl -m 5 -sL -o /dev/null -w "%{http_code} | %{url_effective}\n" "$url"
    done
    ' <<EOF
    $URLS
    EOF
    
    echo "Done!"

    Store these 2 in /etc/systemd/system/

    update_piped_feed.service

    [Unit]
    Description=Update Piped Feed via Docker
    Requires=docker.service
    After=docker.service
    
    [Service]
    Type=oneshot
    User=david
    ExecStart=/usr/local/bin/update_piped_feed.sh
    
    [Install]
    WantedBy=multi-user.target

    update_piped_feed.timer

    [Unit]
    Description=Run Piped Feed Update every hour
    
    [Timer]
    # Starts 1 minute after boot
    OnBootSec=1min
    # Runs every hour on the hour
    OnCalendar=hourly
    # Ensures it doesn't run at exactly the same second as other tasks (saves CPU spikes)
    RandomizedDelaySec=30
    Persistent=true
    
    [Install]
    WantedBy=timers.target

    Then activate the service:

    sudo systemctl daemon-reload
    sudo systemctl enable update_piped_feed.timer
    sudo systemctl start update_piped_feed.timer
    
    # Verify timer status
    sudo systemctl list-timers | grep update_piped_feed
    
    # Monitor the progress (once it was executed)
    sudo journalctl -fu update_piped_feed.service

    EDIT: I originally copied the contend of another systemd .service I use. Now it's the right one. And spelling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions