Skip to content

16.0.1 Video unavailable for SABR, leading to no valid URL to decipher #1123

@acheong08

Description

@acheong08

Steps to reproduce

async function fetchVideoInfo(
    videoId: string,
    reloadPlaybackContext?: ReloadPlaybackContext
  ): Promise<ApiResponse> {
    const innertube = await getInnertube();
    const clientConfig = await getClientConfig();

    const requestParams: Record<string, any> = {
      videoId,
      contentCheckOk: true,
      racyCheckOk: true,
      playbackContext: {
        adPlaybackContext: {
          pyv: true
        },
        contentPlaybackContext: {
          signatureTimestamp: innertube.session.player?.signature_timestamp
        }
      }
    };

    const savedPosition = getPlaybackPosition(currentVideoId);
    if (savedPosition > 0) {
      requestParams.startTimeSecs = Math.floor(savedPosition);
    }

    if (reloadPlaybackContext) {
      requestParams.playbackContext.reloadPlaybackContext =
        reloadPlaybackContext;
    }

    try {
      return await makePlayerRequest({
        clientConfig,
        innertubeRequest: {
          context: innertube.session.context,
          ...requestParams
        }
      });
    } catch (error) {
      console.error(
        '[Player]',
        'Onesie request failed, falling back to Innertube:',
        error
      );
      return await innertube.actions.execute('/player', {
        ...requestParams,
        parse: false
      });
    }
  }
{
    const innertube = await getInnertube();
    const { player } = playerComponents.value;
    if (!player || !innertube) return;

    const sabrAdapter = new SabrStreamingAdapter({
      playerAdapter: new ShakaPlayerAdapter(),
      clientInfo: {
        osName: innertube.session.context.client.osName,
        osVersion: innertube.session.context.client.osVersion,
        clientName: parseInt(
          Constants.CLIENT_NAME_IDS[
            innertube.session.context.client
              .clientName as keyof typeof Constants.CLIENT_NAME_IDS
          ]
        ),
        clientVersion: innertube.session.context.client.clientVersion
      }
    });

    sabrAdapter.onMintPoToken(async () => {
      if (!playbackWebPoToken) {
        // For live streams, we must block and wait for the PO token as it's sometimes required for playback to start.
        // For VODs, we can mint the token in the background to avoid delaying playback, as it's not immediately required.
        // While BotGuard is pretty darn fast, it still makes a difference in user experience (from my own testing).
        if (isLive) {
          await mintContentWebPO();
        } else {
          mintContentWebPO().then();
        }
      }

      return playbackWebPoToken || coldStartToken || '';
    });

    sabrAdapter.onReloadPlayerResponse(async (reloadPlaybackContext) => {
      const apiResponse = await fetchVideoInfo(
        currentVideoId,
        reloadPlaybackContext
      );

      if (!apiResponse) {
        console.error('[Player]', 'Failed to reload player response');
        return;
      }

      const videoInfo = new YT.VideoInfo(
        [ apiResponse ],
        innertube.actions,
        clientPlaybackNonce
      );
      // Log streaming URL for debugging
      console.info(
        '[Player]',
        'Reloaded streaming URL:',
        videoInfo.streaming_data?.server_abr_streaming_url
      );
      sabrAdapter.setStreamingURL(
        await innertube.session.player!.decipher(
          videoInfo.streaming_data?.server_abr_streaming_url
        )
      );
      sabrAdapter.setUstreamerConfig(
        videoInfo.player_config?.media_common_config
          .media_ustreamer_request_config?.video_playback_ustreamer_config
      );
    });

    sabrAdapter.attach(player);
    playerComponents.value.sabrAdapter = sabrAdapter;
  }

From https://github.com/LuanRT/kira/

Failure Logs

{
  "success": true,
  "status_code": 200,
  "data": {
    "responseContext": {
      "mainAppWebResponseContext": {}
    },
    "playabilityStatus": {
      "status": "UNPLAYABLE",
      "reason": "Video unavailable",
      "errorScreen": {
        "playerErrorMessageRenderer": {
          "subreason": {
            "simpleText": "This content isn’t available."
          },
          "reason": {
            "simpleText": "Video unavailable"
          },
          "thumbnail": {
            "thumbnails": [
              {
                "url": "//s.ytimg.com/yts/img/meh7-vflGevej7.png",
                "width": 140,
                "height": 100
              }
            ]
          },
          "icon": {
            "iconType": "ERROR_OUTLINE"
          }
        }
      },
      "contextParams": "Q0FFU0FnZ0M="
    },
    "videoDetails": {
      "title": "The TikTok Situation Is A Nightmare",
      "thumbnail": {
        "thumbnails": [
          {
            "url": "https://i.ytimg.com/vi/YBAvcPXu9BQ/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBQG29QnYWtgJj4W9RyL8uzr9K-Kg",
            "width": 168,
            "height": 94
          },
          {
            "url": "https://i.ytimg.com/vi/YBAvcPXu9BQ/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAnHl6bKWxyciAJivnsDpZxT5Y_Fg",
            "width": 196,
            "height": 110
          },
          {
            "url": "https://i.ytimg.com/vi/YBAvcPXu9BQ/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBJ3fSRNuF3aGXcqZ9_U2Ddu4qlYg",
            "width": 246,
            "height": 138
          },
          {
            "url": "https://i.ytimg.com/vi/YBAvcPXu9BQ/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBuq9NowhQ2-XC0kJ2iuJyVR2hu4g",
            "width": 336,
            "height": 188
          },
          {
            "url": "https://i.ytimg.com/vi_webp/YBAvcPXu9BQ/maxresdefault.webp",
            "width": 1920,
            "height": 1080
          }
        ]
      },
      "author": "Vaush",
      "isLiveContent": false
    }
  }
}

Error: No valid URL to decipher

Code: 1007

Expected behavior

Return SABR URLs

Current behavior

Sabr URL is undefined

Version

Default

Anything else?

This does not appear to be an IP block. Tested with residential IP and blocked IP. Blocked IP returns error "[Player] Unplayable: Sign in to confirm you’re not a bot index-Bz_ncNvi.js:1:1835527"

Checklist

  • I am running the latest version.
  • I checked the documentation and found no answer.
  • I have searched the existing issues and made sure this is not a duplicate.
  • I have provided sufficient information.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions