[RELEASE] Stream Link/File Manager for Channels [Streaming Library Manager Extension]

Happy 12,000+ Docker downloads, Stream Link/File Manger!

image


I was hoping to get this all out by the 10K threshold, but I missed it. So instead, I'll now announce that as of v2025.12.15.1330, SLM has been 85% rewritten from the ground up in an effort to simplify interactions, make maintenance easier and cleaner, introduce new capabilities, improve performance, and future proof against planned and unplanned functionality.

These changes include, but are not limited to:

  • A single, clean location called 'Manage Program' has been created for adding and editing all programs, including videos. This completely deprecates 'Add Programs', 'Modify Programs', and 'Manage Videos'. Details can be found here:
  • Searching has clearer messaging and unlimited filter functionality. Details here:
  • 'New & Updated' is now a range of dates instead of just a single day. Details here:
  • Instead of manually searching using either of the two methods above, you can now have a 'Feed' run on a regular schedule that will build up the results until you are ready for review. Further, you can have results be automatically bookmarked/hidden using the 'Auto-Mapping' functionality. Complete details here:
  • Bookmarking/Hiding can now be accomplished in one step in an expanded search/feed results area. You no longer have to go through the two screen process, although that option is still available by selecting one the of 'edit' choices. Further, there are massive amounts of 'quick actions' you can do while executing, such as setting watched/unwatched status, assigning labels, importing metadata, and more! Further information can be found here:
  • When adding a manual program, all necessary selections happen on the first screen. Learn more here:
  • YouTube Playlists that are imported into SLM can be kept in sync as new videos are added, as if they were new episodes. This is discussed here:
  • When modifying a program, especially a TV Show, there is no longer a checkbox for seasons and all episodes or anything similar. Instead, there is a box for 'Global' controls that can push modifications down to individual items using either direct selection (i.e., 'All Season 02', 'Everything through Season 06') or with filter functionality. As part of this, only 100 detail items are loaded at a clip, meaning that this much faster and shows with thousands of episodes are no longer a performance or crash issue! More about this can be found here:
  • Movies and TV Shows can now have metadata imported, both from JustWatch and video providers like YouTube, depending upon your source. This is especially useful when Channels DVR cannot find a match or the match is missing pertinent information like the duration. Additionally, automation tries to correct imported metadata on a regular basis if certain conditions are met. And as part of all these changes, fixed the summary field so it now remembers carriage returns upon save. Much of this can be reviewed here:
  • Ability for new TV Show episodes to automatically have metadata imported. This is covered in part here:
  • Video order on the webpage is reflective of the value set by users and generally matches to what would be seen in Channels DVR (there are some disagreements of exactness like how to order items that have the same release date or ignoring articles with alphabetical sorting). See this for additional details:
  • 'Check Availability' has been replaced with 'Examine', which means the user can see the original search results data for a program, including its description. More information here:
  • Users can choose to add 'TV Show Titles' and/or 'Episode Titles' to Stream Link/File file names. Details here:

And these are just the big ticket items! There are so many small adjustments and changes that are just too numerous to list. Suffice to say, the entire experience has changed and will be much easier for new users, but still familiar to long-term ones.

Thanks so much for the update.
The program has been very helpful.

Would I use the volume name in the "value" portion of the environmental variables?

Yes, as shown in the example I linked, you need to add the env var value -- plus add your new volume to the separate volumes: section of the Compose.

Like this (assuming the Volume you created was named channels-dvr):

services:
  slm:
    image: ghcr.io/babsonnexus/stream-link-manager-for-channels:${TAG:-latest}
    container_name: slm
    ports:
      - ${SLM_PORT:-5000}:5000
    volumes:
      - ${SLM_HOST_FOLDER:-slm_files}:/app/program_files
      - ${SLM_MEDIA_FOLDER}:/app/channels_folder
    environment:
      - TZ=${TIMEZONE:-UTC}
    restart: unless-stopped

volumes:
  slm_files:
  channels-dvr:
    external: true

With env var values similar to these:

TAG=latest
SLM_PORT=5000
SLM_HOST_FOLDER=slm_files
SLM_MEDIA_FOLDER=channels-dvr
TZ=America/New_York

I've got HBO Max setup as HBO Max as a provider, but ever since the name change back to HBO Max, none of the stream links do anything. Is there a fix for this? I can't find an answer in the faq

image

It's a HBO Max problem:

This FAQ does cover this situation:

https://github.com/babsonnexus/stream-link-manager-for-channels/wiki/Troubleshooting-&-FAQ#slm-a-stream-link-generated-and-the-movie-or-show-is-available-in-my-media-player-client-but-when-i-click-to-launch-it-i-get-an-error-it-works-in-the-web-though--the-stream-link-works-on-one-platform-like-ipad-os-but-does-not-work-in-another-like-tvos

I'm 99% certain if I did an app teardown I would find that TWD neglected to update to accept hbomax.com and hbomax:// and still just has "max" in there.

It might be interesting to do a Stream Link Mapping of a simple string replacement of "hbomax" to just "max" and see if it launches. In the web when I tested it did autoforward back to hbomax, so it might work. I don't have an account at the moment to check, though, so we'll have to depend on you!

1 Like

Thanks for the suggestion. I'll try it tonight.

I set up HBO Max around 12/1. Have not seen any issues when tuning to watch. Just my 2 cents!!

Are you on Android? If so, this might be only an Apple issue.

Well thank you for all your help. Ive taken your advice and all seems to go well up to the point when deploying the stack, I get access denied by my windows share. Im aware this is my problem do to some sort of networking issue I have. At this point I'm just about giving up on it.
Ive installed Samba, and cifs on both machines. went though permissions, and made sure cifs was enabled on windows. I even went as far as trying to install NFS and using that, with no joy. Ive tryed to setup the Volume using the different versions and the only one that doesnt give me a variable error is the v3.0, which in turns tells me i dont have permission. So with that being said (i know long winded) I wont be wasting anymore of your guys time, that way you can help someone that actually know what they are doing. Again Thank you.

Firetv Cube but I can test on an AppleTv if you’d like

To clarify my issue, Channels does nothing when clicking watch on an HBO Max stream link on Apple TV. All other services it launches the appropriate app.

Yep, that's Android-based. Looks like WBD did the right thing on that platform. If you can check your Apple TV, that'd be great just for additional confirmation that it's localized to Apple.

Not doing anything is the same as an error, but I've updated the FAQ to make that clear. Basically, Channels sends the command but nothing responds, therefore nothing happens! I know for a fact that Kanopy on Android is like that, too, so have experienced the same. A very weird one is Hoopla where it opens the mobile app version because of bad coding on their side.

Just tried on AppleTV 4K and it doesn’t do anything when hitting watch!!

This fixed it on Apple TV and iOS for me. Thanks for the suggestion.

Ive gotten the Windows standalone installed. Setup and listed one tv show, it shows in Channels dvr but when I click on it it doesnt open the paramount+ essentials app I have installed. I get an error saying "I dont have an app to use for that" Its on an Android/ Google Tv with android 14. Ive read in previous past that this might be an issue? Ive also check to make sure I have the file extensions showing. They arent listed as Text.

See the Troubleshooting & FAQ:

image


That said, I took a crack at this, but I don't have Paramount+ to test in an app (this does work in the web). I tore down the Paramount+ app and found some errors in the Android Manifest for how it handles deep links.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="36" android:compileSdkVersionCodename="16" android:requiredSplitTypes="base__abi,base__density" android:splitTypes="" package="com.cbs.ca" platformBuildVersionCode="36" platformBuildVersionName="16">
    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <queries>
        <intent>
            <action android:name="android.intent.action.VIEW"/>
            <data android:scheme="http"/>
        </intent>
        <intent>
            <action android:name="android.support.customtabs.action.CustomTabsService"/>
        </intent>
        <intent>
            <action android:name="android.intent.action.VIEW"/>
            <data android:scheme="https"/>
        </intent>
        <package android:name="com.google.android.apps.tv.launcherx"/>
        <package android:name="com.google.android.tvlauncher"/>
        <package android:name="com.google.android.tvrecommendations"/>
        <package android:name="com.google.android.gms.policy_cast_dynamite"/>
        <intent>
            <action android:name="com.android.vending.billing.InAppBillingService.BIND"/>
        </intent>
    </queries>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:minSdkVersion="34" android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
    <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION"/>
    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID"/>
    <uses-permission android:name="android.permission.AD_SERVICES_CONFIG"/>
    <uses-feature android:name="android.software.leanback" android:required="false"/>
    <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
    <uses-permission android:name="com.android.vending.BILLING"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
    <permission android:name="com.cbs.ca.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" android:protectionLevel="signature"/>
    <uses-permission android:name="com.cbs.ca.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE"/>
    <application android:allowBackup="false" android:appComponentFactory="androidx.core.app.CoreComponentFactory" android:enableOnBackInvokedCallback="false" android:extractNativeLibs="false" android:fullBackupContent="@xml/auth_backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:name="com.cbs.app.screens.main.MainApplication" android:networkSecurityConfig="@xml/network_security_config" android:supportsRtl="true" android:theme="@style/BaseAppTheme">
        <service android:name="com.paramount.android.pplus.features.device.home.channels.core.internal.jobservice.SyncChannelJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
        <service android:name="com.paramount.android.pplus.features.device.home.channels.core.internal.jobservice.SyncProgramJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
        <service android:name="com.paramount.android.pplus.features.device.home.channels.core.internal.jobservice.MigrationJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
        <receiver android:enabled="true" android:exported="true" android:name="com.paramount.android.pplus.features.device.home.channels.core.receiver.LauncherReceiver">
            <intent-filter>
                <action android:name="com.google.android.mediahome.action.INITIALIZE_PROGRAMS"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>
        <property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY" android:value="true"/>
        <profileable android:shell="true"/>
        <uses-library android:name="org.apache.http.legacy" android:required="false"/>
        <activity android:configChanges="orientation|screenSize" android:name="com.cbs.app.screens.main.MainActivity" android:windowSoftInputMode="stateUnchanged|adjustPan"/>
        <activity android:name="com.cbs.app.screens.pin.TimeScreenPinActivity"/>
        <activity android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize" android:launchMode="singleTop" android:name="com.paramount.android.pplus.player.mobile.integration.ui.VideoPlayerActivity" android:supportsPictureInPicture="true" android:taskAffinity="com.paramount.android.pplus.player.mobile.internal.ui.VideoPlayerActivity" android:theme="@style/BaseAppTheme.VideoPlayer" android:windowSoftInputMode="adjustPan"/>
        <activity android:name="com.paramount.android.pplus.widget.item.selector.mobile.ui.ItemSelectorActivity" android:theme="@style/BaseAppTheme.Transparent"/>
        <activity android:exported="true" android:launchMode="singleTask" android:name="com.paramount.android.pplus.features.splash.mobile.integration.SplashActivity" android:theme="@style/AppTheme.Fullscreen.Splash">
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="http"/>
                <data android:scheme="https"/>
                <data android:scheme="pplusintl"/>
                <data android:host="www.paramountplus.com"/>
                <data android:path=""/>
                <data android:path="/"/>
                <data android:pathPrefix="/account"/>
                <data android:pathPrefix="/brands"/>
                <data android:pathPrefix="/browse"/>
                <data android:pathPrefix="/cancel-subscription"/>
                <data android:pathPrefix="/collections"/>
                <data android:pathPrefix="/downloads"/>
                <data android:pathPrefix="/hub"/>
                <data android:pathPrefix="/live-tv"/>
                <data android:pathPrefix="/more"/>
                <data android:pathPrefix="/movies"/>
                <data android:pathPrefix="/my-list"/>
                <data android:pathPrefix="/news"/>
                <data android:pathPrefix="/profiles"/>
                <data android:pathPrefix="/search"/>
                <data android:pathPrefix="/settings"/>
                <data android:pathPrefix="/shows"/>
                <data android:pathPrefix="/upgrade_offer"/>
                <data android:pathPrefix="/user-profile"/>
                <data android:pathPrefix="/watchlist"/>
                <data android:pathPrefix="/watch"/>
            </intent-filter>
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="http"/>
                <data android:scheme="https"/>
                <data android:host="open"/>
                <data android:host="link.us.paramountplus.com"/>
                <data android:host="paramount-us.smart.link"/>
                <data android:host="www.paramountplus.com"/>
                <data android:host="link.tv.cbs.com"/>
                <data android:host="cbsaa-alternate.app.link"/>
                <data android:host="cbsaa.test-app.link"/>
                <data android:host="cbsaa-alternate.test-app.link"/>
                <data android:host="paramount-intl.smart.link"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="tl-a48da0aa"/>
            </intent-filter>
        </activity>
        <meta-data android:name="io.branch.sdk.BranchKey" android:value="key_live_caHUGEJZd3MH99BLqLiPbgdpCtlM5iAh"/>
        <meta-data android:name="io.branch.sdk.BranchKey.test" android:value="key_test_fpUSLtT1h5JG80tKqJxflelmwsjLXbzx"/>
        <meta-data android:name="io.branch.sdk.TestMode" android:value="false"/>
        <receiver android:exported="false" android:name="com.cbs.app.pushNotification.BrazeBroadcastReceiver">
            <intent-filter>
                <action android:name="com.braze.push.intent.NOTIFICATION_RECEIVED"/>
                <action android:name="com.braze.push.intent.NOTIFICATION_OPENED"/>
                <action android:name="com.braze.push.intent.NOTIFICATION_DELETED"/>
            </intent-filter>
        </receiver>
        <provider android:authorities="com.cbs.ca.androidx-startup" android:exported="false" android:name="androidx.startup.InitializationProvider">
            <meta-data android:name="com.paramount.avia.tracking.data.SharedPrefsInitializer" android:value="androidx.startup"/>
            <meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer" android:value="androidx.startup"/>
            <meta-data android:name="androidx.lifecycle.ProcessLifecycleInitializer" android:value="androidx.startup"/>
            <meta-data android:name="androidx.profileinstaller.ProfileInstallerInitializer" android:value="androidx.startup"/>
            <meta-data android:name="okhttp3.internal.platform.PlatformInitializer" android:value="androidx.startup"/>
        </provider>
        <activity android:name="com.paramount.android.pplus.upsell.home.mobile.UpsellHomeActivity" android:windowSoftInputMode="stateUnchanged|adjustPan"/>
        <activity android:name="com.paramount.android.pplus.tvprovider.mobile.internal.ProviderLoginActivity"/>
        <activity android:exported="true" android:name="com.paramount.android.pplus.upsell.planpicker.mobile.home.ManagePlanActivity" android:theme="@style/BaseAppTheme"/>
        <activity android:exported="false" android:name="com.paramount.android.pplus.features.redfast.mobile.RedfastActivity"/>
        <activity android:exported="false" android:name="com.paramount.android.pplus.features.accountdelete.disclaimer.mobile.api.DisclaimerActivity"/>
        <activity android:exported="true" android:name="com.paramount.android.pplus.prompts.mobile.PromptActivity"/>
        <activity android:exported="true" android:launchMode="singleTask" android:name="com.paramount.android.pplus.tools.cast.mobile.client.google.impl.internal.ui.ExpandedControlsActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
            </intent-filter>
        </activity>
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>
        <meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME" android:value="com.paramount.android.pplus.tools.cast.mobile.client.google.impl.internal.CastOptionsProvider"/>
        <activity android:exported="false" android:name="com.paramount.android.pplus.billing.ui.mobile.integration.BillingActivity"/>
        <activity android:exported="false" android:name="com.paramount.android.pplus.features.password.sharing.mobile.PasswordSharingActivity"/>
        <activity android:name="com.paramount.android.pplus.webview.mobile.internal.WebViewActivity" android:theme="@style/BaseAppTheme"/>
        <provider android:authorities="com.cbs.ca.fileprovider" android:exported="false" android:grantUriPermissions="true" android:name="com.paramount.android.pplus.tools.storage.impl.cacheFIleProvider.CustomFileProvider">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/>
        </provider>
        <receiver android:exported="false" android:name="com.viacbs.android.MobileShareOptionSelectedListener"/>
        <provider android:authorities="com.newrelic.android.agent.nrprovider.com.cbs.ca" android:enabled="@bool/is_app_launch_time_tracker_enabled" android:exported="false" android:initOrder="200" android:name="com.newrelic.agent.android.rum.contentprovider.NewRelicAppContentProvider"/>
        <activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:exported="true" android:launchMode="singleTop" android:name="com.viacom.android.auth.internal.mvpd.customtabs.CustomTabRedirectReceiverActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:host="com.cbs.ca" android:scheme="viacom"/>
            </intent-filter>
        </activity>
        <activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:name="com.viacom.android.auth.internal.mvpd.customtabs.CustomTabMainActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
        <service android:exported="true" android:name="com.viacom.android.auth.internal.mvpd.customtabs.KeepAliveService"/>
        <service android:exported="false" android:foregroundServiceType="dataSync" android:name="com.paramount.android.pplus.tools.downloader.exoplayer.internal.ExoPlayerDownloaderService">
            <intent-filter>
                <action android:name="com.google.android.exoplayer2.downloadService.action.RESTART"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>
        <service android:exported="true" android:name="com.google.android.exoplayer2.scheduler.PlatformScheduler$PlatformSchedulerService" android:permission="android.permission.BIND_JOB_SERVICE"/>
        <receiver android:exported="false" android:name="com.paramount.android.pplus.tools.downloader.impl.internal.notifications.NotificationActionHandlerBroadcastReceiver">
            <intent-filter>
                <action android:name="com.paramount.android.pplus.tools.downloader.api.notifications.NOTIFICATION_ACTION_FILTER"/>
            </intent-filter>
        </receiver>
        <service android:exported="false" android:name="com.braze.push.BrazeFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
        <activity android:exported="false" android:name="com.adobe.marketing.mobile.assurance.internal.ui.AssuranceActivity" android:theme="@style/AssuranceAppThemeDark"/>
        <service android:exported="false" android:name="com.adobe.marketing.mobile.ExtensionDiscoveryService">
            <meta-data android:name="com.adobe.marketing.mobile.assurance.internal.AssuranceExtension" android:value="Extension"/>
            <meta-data android:name="com.adobe.marketing.mobile.EdgeExtension" android:value="Extension"/>
            <meta-data android:name="com.adobe.marketing.mobile.analytics.internal.AnalyticsExtension" android:value="Extension"/>
            <meta-data android:name="com.adobe.marketing.mobile.lifecycle.LifecycleExtension" android:value="Extension"/>
            <meta-data android:name="com.adobe.marketing.mobile.edge.identity.IdentityExtension" android:value="Extension"/>
            <meta-data android:name="com.adobe.marketing.mobile.identity.IdentityExtension" android:value="Extension"/>
            <meta-data android:name="com.adobe.marketing.mobile.internal.configuration.ConfigurationExtension" android:value="Extension"/>
        </service>
        <activity android:exported="false" android:name="com.google.android.tv.ads.controls.FallbackImageActivity" android:theme="@style/Theme.AppCompat.NoActionBar.Translucent"/>
        <receiver android:exported="false" android:name="com.google.android.gms.cast.framework.media.MediaIntentReceiver"/>
        <service android:exported="false" android:name="com.google.android.gms.cast.framework.ReconnectionService"/>
        <activity android:exported="false" android:name="com.braze.ui.BrazeWebViewActivity"/>
        <activity android:exported="false" android:name="com.braze.ui.activities.ContentCardsActivity"/>
        <activity android:autoRemoveFromRecents="true" android:excludeFromRecents="true" android:exported="false" android:launchMode="singleInstance" android:name="com.braze.push.NotificationTrampolineActivity" android:taskAffinity=".NotificationTrampolineActivity" android:theme="@style/Braze.PushTrampoline.Transparent"/>
        <receiver android:exported="false" android:name="com.braze.push.BrazePushReceiver"/>
        <meta-data android:name="com.bumptech.glide.integration.okhttp3.OkHttpGlideModule" android:value="GlideModule"/>
        <meta-data android:name="com.google.android.play.billingclient.version" android:value="7.0.0"/>
        <activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:exported="false" android:name="com.android.billingclient.api.ProxyBillingActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
        <activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:exported="false" android:name="com.android.billingclient.api.ProxyBillingActivityV2" android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
        <receiver android:exported="true" android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
            </intent-filter>
            <meta-data android:name="com.google.android.gms.cloudmessaging.FINISHED_AFTER_HANDLED" android:value="true"/>
        </receiver>
        <service android:directBootAware="true" android:exported="false" android:name="com.google.firebase.messaging.FirebaseMessagingService">
            <intent-filter android:priority="-500">
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
        <service android:directBootAware="true" android:exported="false" android:name="com.google.firebase.components.ComponentDiscoveryService">
            <meta-data android:name="com.google.firebase.components:com.google.firebase.messaging.FirebaseMessagingKtxRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.messaging.FirebaseMessagingRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.installations.FirebaseInstallationsKtxRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.installations.FirebaseInstallationsRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.FirebaseCommonKtxRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.datatransport.TransportRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
        </service>
        <activity android:exported="false" android:name="com.google.android.gms.common.api.GoogleApiActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
        <service android:directBootAware="false" android:enabled="@bool/enable_system_alarm_service_default" android:exported="false" android:name="androidx.work.impl.background.systemalarm.SystemAlarmService"/>
        <service android:directBootAware="false" android:enabled="@bool/enable_system_job_service_default" android:exported="true" android:name="androidx.work.impl.background.systemjob.SystemJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
        <service android:directBootAware="false" android:enabled="@bool/enable_system_foreground_service_default" android:exported="false" android:name="androidx.work.impl.foreground.SystemForegroundService"/>
        <receiver android:directBootAware="false" android:enabled="true" android:exported="false" android:name="androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver"/>
        <receiver android:directBootAware="false" android:enabled="false" android:exported="false" android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryChargingProxy">
            <intent-filter>
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
            </intent-filter>
        </receiver>
        <receiver android:directBootAware="false" android:enabled="false" android:exported="false" android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryNotLowProxy">
            <intent-filter>
                <action android:name="android.intent.action.BATTERY_OKAY"/>
                <action android:name="android.intent.action.BATTERY_LOW"/>
            </intent-filter>
        </receiver>
        <receiver android:directBootAware="false" android:enabled="false" android:exported="false" android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$StorageNotLowProxy">
            <intent-filter>
                <action android:name="android.intent.action.DEVICE_STORAGE_LOW"/>
                <action android:name="android.intent.action.DEVICE_STORAGE_OK"/>
            </intent-filter>
        </receiver>
        <receiver android:directBootAware="false" android:enabled="false" android:exported="false" android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$NetworkStateProxy">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
        </receiver>
        <receiver android:directBootAware="false" android:enabled="false" android:exported="false" android:name="androidx.work.impl.background.systemalarm.RescheduleReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.TIME_SET"/>
                <action android:name="android.intent.action.TIMEZONE_CHANGED"/>
            </intent-filter>
        </receiver>
        <receiver android:directBootAware="false" android:enabled="@bool/enable_system_alarm_service_default" android:exported="false" android:name="androidx.work.impl.background.systemalarm.ConstraintProxyUpdateReceiver">
            <intent-filter>
                <action android:name="androidx.work.impl.background.systemalarm.UpdateProxies"/>
            </intent-filter>
        </receiver>
        <receiver android:directBootAware="false" android:enabled="true" android:exported="true" android:name="androidx.work.impl.diagnostics.DiagnosticsReceiver" android:permission="android.permission.DUMP">
            <intent-filter>
                <action android:name="androidx.work.diagnostics.REQUEST_DIAGNOSTICS"/>
            </intent-filter>
        </receiver>
        <service android:directBootAware="true" android:exported="false" android:name="androidx.room.MultiInstanceInvalidationService"/>
        <uses-library android:name="androidx.window.extensions" android:required="false"/>
        <uses-library android:name="androidx.window.sidecar" android:required="false"/>
        <receiver android:exported="false" android:name="com.braze.BrazeFlushPushDeliveryReceiver">
            <intent-filter>
                <action android:name="com.braze.FLUSH_EVENTS"/>
            </intent-filter>
        </receiver>
        <activity android:exported="true" android:name="androidx.compose.ui.tooling.PreviewActivity"/>
        <provider android:authorities="com.cbs.ca.firebaseinitprovider" android:directBootAware="true" android:exported="false" android:initOrder="100" android:name="com.google.firebase.provider.FirebaseInitProvider"/>
        <receiver android:directBootAware="false" android:enabled="true" android:exported="true" android:name="androidx.profileinstaller.ProfileInstallReceiver" android:permission="android.permission.DUMP">
            <intent-filter>
                <action android:name="androidx.profileinstaller.action.INSTALL_PROFILE"/>
            </intent-filter>
            <intent-filter>
                <action android:name="androidx.profileinstaller.action.SKIP_FILE"/>
            </intent-filter>
            <intent-filter>
                <action android:name="androidx.profileinstaller.action.SAVE_PROFILE"/>
            </intent-filter>
            <intent-filter>
                <action android:name="androidx.profileinstaller.action.BENCHMARK_OPERATION"/>
            </intent-filter>
        </receiver>
        <service android:exported="false" android:name="com.google.android.datatransport.runtime.backends.TransportBackendDiscovery">
            <meta-data android:name="backend:com.google.android.datatransport.cct.CctBackendFactory" android:value="cct"/>
        </service>
        <service android:exported="false" android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService" android:permission="android.permission.BIND_JOB_SERVICE"/>
        <receiver android:exported="false" android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.AlarmManagerSchedulerBroadcastReceiver"/>
        <provider android:authorities="com.cbs.ca.ProcessLaunchProvider" android:exported="false" android:name="com.conviva.platforms.android.ProcessLaunchProvider"/>
        <meta-data android:name="com.android.vending.splits.required" android:value="true"/>
        <meta-data android:name="com.android.stamp.source" android:value="https://play.google.com/store"/>
        <meta-data android:name="com.android.stamp.type" android:value="STAMP_TYPE_DISTRIBUTION_APK"/>
        <meta-data android:name="com.android.vending.splits" android:resource="@xml/splits0"/>
        <meta-data android:name="com.android.vending.derived.apk.id" android:value="3"/>
    </application>
</manifest>

According to the AI:

❌ Path: /shows/star-trek-strange-new-worlds/video/...
    The manifest only allows /shows as a pathPrefix.
    But once you go deeper into /shows/.../video/..., the filter doesn’t cover it because there’s no pathPrefix="/video" or pathPattern for nested paths.

To get around this, we can try to simplify the link using a Stream Link Mapping:

  • If 'Stream Link' contains: ^(https:\/\/www\.paramountplus\.com\/shows)\/[^\/]+\/video\/([^\/]+)\/.*$

  • For 'Object Type': SHOW (didn't look into how a Movie functions, might have to do something similar)

  • Do this activity: Replace pattern (REGEX) with...

  • Using this: \1/video/\2/

  • Example Base Link: https://www.paramountplus.com/shows/star-trek-strange-new-worlds/video/vD_dS02AvEtutf2mdwdiOU0WZIpkhMPA/star-trek-strange-new-worlds-strange-new-worlds

  • Example Resulting Link: https://www.paramountplus.com/shows/video/vD_dS02AvEtutf2mdwdiOU0WZIpkhMPA/

This may or may not work, you'll have to test. There might be additional modifications you can do as well to get it to work. Here's an example of the same excercise that was done with Peacock to get it working:

@KineticMan, FYI on the above in relation to Peacock and Paramount+ for Fruit Stream Links on Android.

1 Like

Ok, Ill give it a try, between work and a family member passing away it will be a couple of days before I can get to it. Thank you. Ill revisit when i've had a chance.

Ok, well I've tested it and Paramount Plus still wont work, I've tried Peacock and Hulu and they do not work either. I seemed to not be able to get anywhere with this. More than likely its probably Android/ GoogleTv 14 . Don't know where to go from here.

Paramount plus= No app for this error
Peacock= Opens, but to main start page and not the tv show. So still have to look for the show.
Hulu= Does nothing, no error, wont open anything.

It is not. I have several Android/GoogleTV 14 devices and Stream Links work on them. It appears, though, you are running into specific apps that are having problems.

As I said, you'll probably have to play around with this one. Based upon what I've seen, Paramount+ doesn't seem to be happy with anything direct, so you might have to deal with just a generic launch. Try a Stream Link Mapping of anything that contains paramountplus and replace with https://www.paramountplus.com and see if that works just for app launching. From there, you can try the subareas, but the problem appears to be on Paramount's side, so you'll have to reach out to them. Tell them they wrote deep linking incorrectly in the Android Manifest.

@miles, @tobycth3, @Jean0987654321 can you comment on this? When last we discussed in February everything was happy, but maybe something changed?

Looks like Disney broke something in the Android Manifest because this was working before. Since the standalone version of this app is going to be discontinued sometime in the next few months, I doubt they'll fix it. In the short term, you could do a generic mapping to at least open the app at https://www.hulu.com/open. My recommendation is do the Hulu to Disney+ mapping because that works in 98% of situations (some content still isn't in Disney+Hulu yet, for reasons that are beyond me, including a couple of Hulu Originals I know about).


In case anyone is interested in my analysis, here's a part of it (from my AI buddy):

Disney+ succeeds because:

✅ It accepts any path under the domain
✅ It uses server redirects to normalize links
✅ It does not require strict pathPrefix matching
✅ It does not rely on the app to parse the incoming URL directly

Hulu and Paramount+ do the opposite:

❌ They require strict pathPrefix matching
❌ They do not redirect /watch/{id} or /shows/{id} into a normalized format
❌ They rely on the app to parse the incoming URL
❌ They require App Links verification to succeed
❌ If verification fails, Android silently ignores the link

This is why:

    ✅ Disney+ links “just work”
    ❌ Hulu links often do nothing
    ❌ Paramount+ links require rewriting