ftde0 / yt2009

2009 youtube frontend.
Apache License 2.0
193 stars 120 forks source link

[reposted] Apiplayer Issue #160

Open RedFireMRT84 opened 1 week ago

RedFireMRT84 commented 1 week ago

Greetings, I'm sorry for reposting this, I accidentally closed the other one, which is why I reposted this. I've released this project last night: https://github.com/RedFireMRT84/Liinback-v3 I have my own getVideo route on where it loads InnerTube's youtubei/player for Android, and extracts the values for a url of .googlevideo.com and gets the latest quality in mp4 format, downloads the file and converts to a WEBM format in vp8.

My getVideo route:

@app.route('/api/videos/get/<video_id>', methods=['GET'])
def getVideo(video_id):
    url = f'https://www.googleapis.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8&videoId={video_id}'
    headers = {
        'Content-Type': 'application/json',
        'User-Agent': 'com.google.android.youtube/19.02.39 (Linux; U; Android 14) gzip'
    }
    payload = {
        "context": {
            "client": {
                "hl": "en",
                "gl": "US",
                "clientName": "ANDROID",
                "clientVersion": "19.02.39",
                "androidSdkVersion": 34,
                "mainAppWebInfo": {
                    "graftUrl": "/watch?v=" + video_id
                }
            }
        },
        "videoId": video_id
    }
    response = requests.post(url, headers=headers, json=payload)
    data = response.json()
    streaming_data = data.get('streamingData', {})
    formats = streaming_data.get('adaptiveFormats', []) + streaming_data.get('formats', [])
    for f in formats:
        if f.get('audioChannels') == 2 and f.get('mimeType').startswith('video/mp4'):
            video_url = f.get('url')
            if video_url:
                input_file = f'assets/videoplayback.mp4'
                output_file = f'assets/{video_id}.webm'
                if os.path.exists(output_file):
                    return send_from_directory(os.getcwd(), output_file, as_attachment=True)
                with requests.get(video_url, stream=True) as r:
                    with open(input_file, 'wb') as f:
                        for chunk in r.iter_content(chunk_size=8192):
                            f.write(chunk)
                if os.path.exists(input_file):
                    conversion_to_webm_command = ['ffmpeg', '-v', 'verbose', '-i', input_file, '-c:v', 'libvpx', '-b:v', '500k', '-cpu-used', '8', '-vf', 'scale=-1:360', '-c:a', 'libvorbis', '-b:a', '128k', output_file]
                    subprocess.run(conversion_to_webm_command)
                    return send_from_directory(os.getcwd(), output_file, as_attachment=True)
                else:
                    return jsonify({"error": "Failed to download the video"}), 500
    return jsonify({"error": "No video with audioChannels 2 found"}), 404

runs very fine without the apiplayer. But for the apiplayer if I do a video longer than 1:48 seconds, the conversion of the WEBM format gets corrupted most at the times and the apiplayer either crashes your Wii, crashes the Flash emulator itself by: https://gbatemp.net/attachments/img_4810-1-jpg.471605/ Or the video plays but corrupted and skips durations of the video. I really think that the apiplayer itself is causing the getVideo route to be like this on the apiplayer. https://www.youtube.com/watch?v=LtKghUBFdHI

ftde0 commented 1 week ago

assuming you've got all the codec-related stuff right, do you have any instruction to "wait" out if a request is called multiple times?

you don't want 2 downloads and conversions going on at the same time. this was the reason FLV playback was sorta broken on yt2009 for the longest time.

yt2009's example for waiting out multiple sent requests: https://github.com/ftde0/yt2009/commit/9c2900f167ff9130eab0875c7792c0a59a851d56#diff-1fdf8a070322a7cc40777617e5a89b729417eff14d5888bdb8d5f4eea6c8918f

RedFireMRT84 commented 6 days ago

Does YouTube's (/youtubei/player) route even support WEBMs in VP8 format anymore?

ftde0 commented 5 days ago

they don't serve VP8 anymore, WEBMs provided by youtube are VP9

RedFireMRT84 commented 5 days ago

I'm currently trying to figure out a way to get more than 100 videos in the /youtubei/browse?browseId=VL{playlistId} URL to display. My playlist for example has 150 videos. But when I went to loaded the url in my custom route, it only includes 100 videos instead of 150. I'm using the WEB client and the Windows user agent to load the api. Is there another way to get the full lists of videos instead of the maximum of 100 videos to display?

ftde0 commented 5 days ago

open the playlist in desktop youtube, scroll down until the next part renders. you'll see a request with a "continuation token", use that. the continuation token is in the first playlist videos request as the last item. repeat until you don't get a continuation token anymore.