Wie spiele ich Youtube-Videos im ExoPlayer in Android ab?

Lesezeit: 9 Minuten

Benutzer-Avatar
Amit Prajapati

Ich versuche, YouTube-Videos im Exoplayer abzuspielen, aber hier gibt es einige Verwirrung. Ich weiß nicht, was die DASH-URL ist. Ich habe nur eine echte YouTube-URL wie “https://www.youtube.com/watch?v=v1uyQZNg2vE” , ich habe keine Ahnung, wie man eine Bindestrich-URL aus einer echten URL generiert.

Dash-URL:

new Sample("Google Glass",
        "http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?"
        + "as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,as&ip=0.0.0.0&"
        + "ipbits=0&expire=19000000000&signature=255F6B3C07C753C88708C07EA31B7A1A10703C8D."
        + "2D6A28B21F921D0B245CDCF36F7EB54A2B5ABFC2&key=ik0", DemoUtil.TYPE_DASH),

Echte URL:

 https://www.youtube.com/watch?v=v1uyQZNg2vE

  • Haben Sie es geschafft, die DASH-URL zu generieren?

    – Zsolt Boldizsar

    16. Juni 2015 um 10:48 Uhr

  • Gibt es eine gültige Möglichkeit, eine DASH-URL aus der Video-ID zu generieren

    – AndroidXP

    12. Dezember 2017 um 12:26 Uhr

  • @SuryaPrakashKushawah Aber ich denke, YouTube erlaubt nicht, Videos zu extrahieren, inoffizielle Lösung.

    – Amit Prajapati

    19. Dezember 2018 um 9:25 Uhr

Benutzer-Avatar
MARK002-MAB

Ich habe eine Klasse geschrieben, die die tatsächliche YouTube-Video-Streaming-URL für Formate wie DASH und HLS mithilfe von abruft http://www.youtube.com/get_video_info?&video_id=[video_id]&el=info&ps=default&eurl=&gl=US&hl=en URL mit Video-ID, wie von Karim Abdell Salam beschrieben. Ich habe die URL auch in einer App getestet, die verwendet wird ExoPlayer und es funktioniert:

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Map;
import java.util.TreeMap;

/**
 * Represents youtube video information retriever.
 */
public class YouTubeVideoInfoRetriever
{
    private static final String URL_YOUTUBE_GET_VIDEO_INFO = "http://www.youtube.com/get_video_info?&video_id=";

    public static final String KEY_DASH_VIDEO = "dashmpd";
    public static final String KEY_HLS_VIDEO = "hlsvp";

    private TreeMap<String, String> kvpList = new TreeMap<>();

    public void retrieve(String videoId) throws IOException
    {
        String targetUrl = URL_YOUTUBE_GET_VIDEO_INFO + videoId+"&el=info&ps=default&eurl=&gl=US&hl=en";
        SimpleHttpClient client = new SimpleHttpClient();
        String output = client.execute(targetUrl, SimpleHttpClient.HTTP_GET, SimpleHttpClient.DEFAULT_TIMEOUT);
        parse(output);
    }

    public String getInfo(String key)
    {
        return kvpList.get(key);
    }

    public void printAll()
    {
        System.out.println("TOTAL VARIABLES=" + kvpList.size());

        for(Map.Entry<String, String> entry : kvpList.entrySet())
        {
            System.out.print( "" + entry.getKey() + "=");
            System.out.println("" + entry.getValue() + "");
        }
    }

    private void parse(String data) throws UnsupportedEncodingException
    {
        String[] splits = data.split("&");
        String kvpStr = "";

        if(splits.length < 1)
        {
            return;
        }

        kvpList.clear();

        for(int i = 0; i < splits.length; ++i)
        {
            kvpStr = splits[i];

            try
            {
                // Data is encoded multiple times
                kvpStr = URLDecoder.decode(kvpStr, SimpleHttpClient.ENCODING_UTF_8);
                kvpStr = URLDecoder.decode(kvpStr, SimpleHttpClient.ENCODING_UTF_8);

                String[] kvpSplits = kvpStr.split("=", 2);

                if(kvpSplits.length == 2)
                {
                    kvpList.put(kvpSplits[0], kvpSplits[1]);
                }
                else if(kvpSplits.length == 1)
                {
                    kvpList.put(kvpSplits[0], "");
                }
            }
            catch (UnsupportedEncodingException ex)
            {
                throw ex;
            }
        }
    }

    public static class SimpleHttpClient
    {
        public static final String ENCODING_UTF_8 = "UTF-8";
        public static final int DEFAULT_TIMEOUT = 10000;

        public static final String HTTP_GET = "GET";

        public String execute(String urlStr, String httpMethod, int timeout) throws IOException
        {
            URL url = null;
            HttpURLConnection conn = null;
            InputStream inStream = null;
            OutputStream outStream = null;
            String response = null;

            try
            {
                url = new URL(urlStr);
                conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(timeout);
                conn.setRequestMethod(httpMethod);

                inStream = new BufferedInputStream(conn.getInputStream());
                response = getInput(inStream);
            }
            finally
            {
                if(conn != null && conn.getErrorStream() != null)
                {
                    String errorResponse = " : ";
                    errorResponse = errorResponse + getInput(conn.getErrorStream());
                    response = response + errorResponse;
                }

                if (conn != null)
                {
                    conn.disconnect();
                }
            }

            return response;
        }

        private String getInput(InputStream in) throws IOException
        {
            StringBuilder sb = new StringBuilder(8192);
            byte[] b = new byte[1024];
            int bytesRead = 0;

            while (true)
            {
                bytesRead = in.read(b);
                if (bytesRead < 0)
                {
                    break;
                }
                String s = new String(b, 0, bytesRead, ENCODING_UTF_8);
                sb.append(s);
            }

            return sb.toString();
        }

    }
}

Hier ist der Testcode:

public static void main(String[] args)
{
    String youTubeVideoID = "v1uyQZNg2vE";

    YouTubeVideoInfoRetriever retriever = new YouTubeVideoInfoRetriever();

    try
    {
        retriever.retrieve(youTubeVideoID);
        System.out.println(retriever.getInfo(YouTubeVideoInfoRetriever.KEY_DASH_VIDEO));
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

  • Gute Antwort! Vielen Dank!

    – user486312

    13. März 2017 um 18:57 Uhr

  • @ MARK002-MAB, ich habe den obigen Code ausprobiert, seine Arbeit funktioniert nur vorübergehend. Er schlägt nach einiger Zeit fehl

    – Magesh Pandian

    19. April 2017 um 13:27 Uhr

  • @MARK002-MAB Vielen Dank für Ihre Antwort, ich habe eine YouTube-URL, wie kann ich im Exoplayer spielen

    – Magesh Pandian

    25. April 2017 um 3:16 Uhr

  • Würde dies gegen die Nutzungsbedingungen von YouTube verstoßen und dazu führen, dass meine App aus dem Play Store entfernt wird, wenn ich diese Methode verwende?

    – MichaelStoddart

    27. April 2019 um 10:25 Uhr

  • @MichaelStoddart Ja. Es ist eine Möglichkeit. Ich habe irgendwo gelesen, dass die Verwendung anderer als der bereitgestellten Methoden eine Verletzung sein kann. Sie gilt für alle Google-Dienste und -APIs.

    – MARK002-MAB

    27. April 2019 um 10:29 Uhr

Benutzer-Avatar
Karim Abdell Salam

Ich hatte das gleiche Problem, aber ich habe endlich die einfachste Lösung gefunden und sie funktioniert so gut

  1. Zuerst müssen Sie diese URL aufrufen.

    HTTP-GET: https://www.youtube.com/get_video_info?&video_id=[video_id]&el=info&ps=default&eurl=&gl=DE&hl=en

und vergessen Sie nicht, die letzte ID durch die Ziel-ID zu ersetzen.

  1. Jetzt werden Sie aufgefordert, eine Datei namens get_video_info ohne Erweiterung herunterzuladen.
  2. Versuchen Sie, diese Datei mit Notepad und so zu öffnen.
  3. Jetzt haben Sie die richtigen Daten, aber Sie können sie nicht lesen, weil sie codiert sind. Sie benötigen einen HTML-Decoder, um diese Daten zu verwenden. Verwenden Sie diesen:
    http://meyerweb.com/eric/tools/dencoder/

– Fügen Sie einfach Ihre Daten ein und drücken Sie mehrmals decodieren, um sicherzustellen, dass sie gut decodiert werden

Suchen Sie schließlich nach einem Schlüssel namens dashmpd

und genieße deine URL

Oder verwenden Sie diese einfache Lösung

private void extractYoutubeUrl() {
    @SuppressLint("StaticFieldLeak") YouTubeExtractor mExtractor = new YouTubeExtractor(this) {
        @Override
        protected void onExtractionComplete(SparseArray<YtFile> sparseArray, VideoMeta videoMeta) {
            if (sparseArray != null) {
                playVideo(sparseArray.get(17).getUrl());
            }
        }
    };
    mExtractor.extract(mYoutubeLink, true, true);

implementation 'com.github.HaarigerHarald:android-youtubeExtractor:v1.7.0'

  • Funktioniert nicht reason=Invalid+parameters.&status=fail&errorcode=2 das habe ich bekommen

    – AkshayT

    28. März 2018 um 16:59 Uhr

  • Hallo @KarimAbdellSalam, können wir Live-Streaming von YouTube im Exoplayer über Ihre Bibliothek abspielen.

    – Shafqat Kamal

    8. Juli 2020 um 15:25 Uhr

  • Veraltet und funktioniert nicht mehr.

    – Johannes

    18. Oktober 2021 um 13:44 Uhr

Benutzer-Avatar
GAG’sB

Sie müssen die HTTP-Antwort von der YouTube-URL (in Ihrem Fall echte URL) abrufen und dann nach dem Abschnitt “url_encoded_fmt_stream_map” suchen. In diesem Abschnitt erhalten Sie einen URI, der zweimal dekodiert werden muss, um die gesuchte DASH-URL zu erhalten.

  • Veraltet und funktioniert nicht mehr.

    – Johannes

    18. Oktober 2021 um 13:48 Uhr

Um YouTube-Videos im Exoplayer abzuspielen, können wir diese Bibliothek verwenden

https://github.com/HaarigerHarald/android-youtubeExtractor

und holen Sie sich einfach die URL so und spielen Sie dann in Exoplyer

String youtubeLink = "http://youtube.com/watch?v=xxxx";

new YouTubeExtractor(this) {
    @Override
    public void onExtractionComplete(SparseArray<YtFile> ytFiles, VideoMeta vMeta) {
        if (ytFiles != null) {
            int itag = 22;
        String downloadUrl = ytFiles.get(itag).getUrl();
        }
    }
}.extract(youtubeLink, true, true);

Das ist die verwendete Bibliothek

implementation 'com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT'

Das ist die Basis-URL, die ihnen die Video-ID hinzufügt

val YouTubeBase="https://www.youtube.com/watch?v="

das ist Bibliothek verwendet
Ich werde eine Schleife verwenden, um die gesamte Videoqualität (420.720.180) zu erhalten, denn wenn das Video die 1080 nicht enthält, funktioniert es nicht mit Ihnen, sodass ich für die gesamte Qualität eine Schleife verwende
Wenn es jedoch mehr Qualität gefunden hat, wird es die beste Qualität auswählen. Sie können dies mit einem umgekehrten Array namens iTags bearbeiten, wenn Sie eine niedrige Qualität erhalten möchten

    object : YouTubeExtractor(requireContext()) {
        override fun onExtractionComplete(
            ytFiles: SparseArray<YtFile>?,
            videoMeta: VideoMeta?
        ) {
            if (ytFiles != null) {

                val iTag = 137//tag of video 1080
                val audioTag = 140 //tag m4a audio
                // 720, 1080, 480
                var videoUrl = ""
                val iTags: List<Int> = listOf(22, 137, 18)
                for (i in iTags) {
                    val ytFile = ytFiles.get(i)
                    if (ytFile != null) {
                        val downloadUrl = ytFile.url
                        if (downloadUrl != null && downloadUrl.isNotEmpty()) {
                            videoUrl = downloadUrl
                        }
                    }
                }
                if (videoUrl == "")
                    videoUrl = ytFiles[iTag].url
                val audioUrl = ytFiles[audioTag].url
                val audioSource: MediaSource = ProgressiveMediaSource
                    .Factory(DefaultHttpDataSource.Factory())
                    .createMediaSource(MediaItem.fromUri(audioUrl))
                val videoSource: MediaSource = ProgressiveMediaSource
                    .Factory(DefaultHttpDataSource.Factory())
                    .createMediaSource(MediaItem.fromUri(videoUrl))
                player?.setMediaSource(
                    MergingMediaSource(true, videoSource, audioSource), true
                )
            }
        }

    }.extract(youtubeLink)

Das ist mein Code im letzten Projekt, von dem ich hoffe, dass es Ihnen in der verwendeten Bibliothek mit dem Exo-Player helfen kann

package com.hamdy.showtime.ui.ui.video_player

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.exoplayer2.ExoPlayer
import com.hamdy.showtime.databinding.FragmentVideoPlayerBinding
import at.huber.youtubeExtractor.VideoMeta
import at.huber.youtubeExtractor.YtFile
import android.util.SparseArray
import at.huber.youtubeExtractor.YouTubeExtractor
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.MergingMediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.util.Util
import com.hamdy.showtime.ui.util.YouTubeBase


class VideoPlayerFragment : Fragment(), Player.Listener {
    private lateinit var youtubeLink: String
    private lateinit var binding: FragmentVideoPlayerBinding
    var player: ExoPlayer? = null
    private var playWhenReady = true
    private var currentWindow = 0
    private var playbackPosition = 0L

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentVideoPlayerBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        youtubeLink = YouTubeBase + arguments?.get("url").toString()

        initializePlayer()

    }

    private fun initializePlayer() {
        player = ExoPlayer.Builder(requireContext()).build()
        binding.videoView.player = player

        object : YouTubeExtractor(requireContext()) {
            override fun onExtractionComplete(
                ytFiles: SparseArray<YtFile>?,
                videoMeta: VideoMeta?
            ) {
                if (ytFiles != null) {

                    val iTag = 137//tag of video 1080
                    val audioTag = 140 //tag m4a audio
                    // 720, 1080, 480
                    var videoUrl = ""
                    val iTags: List<Int> = listOf(22, 137, 18)
                    for (i in iTags) {
                        val ytFile = ytFiles.get(i)
                        if (ytFile != null) {
                            val downloadUrl = ytFile.url
                            if (downloadUrl != null && downloadUrl.isNotEmpty()) {
                                videoUrl = downloadUrl
                            }
                        }
                    }
                    if (videoUrl == "")
                        videoUrl = ytFiles[iTag].url
                    val audioUrl = ytFiles[audioTag].url
                    val audioSource: MediaSource = ProgressiveMediaSource
                        .Factory(DefaultHttpDataSource.Factory())
                        .createMediaSource(MediaItem.fromUri(audioUrl))
                    val videoSource: MediaSource = ProgressiveMediaSource
                        .Factory(DefaultHttpDataSource.Factory())
                        .createMediaSource(MediaItem.fromUri(videoUrl))
                    player?.setMediaSource(
                        MergingMediaSource(true, videoSource, audioSource), true
                    )
                    player?.prepare()
                    player?.playWhenReady = playWhenReady
                    player?.seekTo(currentWindow, playbackPosition)
                    player?.addListener(this@VideoPlayerFragment)
                }
            }

        }.extract(youtubeLink)

    }

    override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
        if (playbackState == Player.STATE_READY) {
            binding.progressBar.visibility = View.INVISIBLE
        } else {
            binding.progressBar.visibility = View.VISIBLE
        }
    }


    override fun onStart() {
        super.onStart()
        if (Util.SDK_INT >= 24 || player == null) {
            initializePlayer()

        }
    }

    override fun onResume() {
        super.onResume()
        if (Util.SDK_INT < 24 || player == null) {
            initializePlayer()

        }
    }

    override fun onPause() {
        if (Util.SDK_INT < 24) releasePlayer()
        super.onPause()
    }

    private fun releasePlayer() {
        if (player != null) {
            playWhenReady = player!!.playWhenReady
            playbackPosition = player!!.currentPosition
            currentWindow = player!!.currentMediaItemIndex
            player?.release()
            player = null
        }

    }
}

1049470cookie-checkWie spiele ich Youtube-Videos im ExoPlayer in Android ab?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy