Ami*_*ati 36 java youtube android exoplayer
我试图在exoplayer中播放youtube视频,但这里有一些混乱我不知道什么是DASH url,我只有真正的youtube网址,如" https://www.youtube.com/watch?v=v1uyQZNg2vE ",我不知道如何生成破折号网址形式真实的网址.
短划线网址:
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),
Run Code Online (Sandbox Code Playgroud)
真实网址:
https://www.youtube.com/watch?v=v1uyQZNg2vE
Run Code Online (Sandbox Code Playgroud)
MAR*_*MAB 12
我写过一个课程,使用http://www.youtube.com/get_video_info?&video_id=[video_id]&el=info&ps=default&eurl=&gl=US&hl=en url与DASH和HLS等格式检索实际的YouTube视频流网址视频ID由Karim Abdell Salam描述.我还在使用ExoPlayer的应用程序中测试了URL ,它可以工作:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是测试代码:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
我有同样的问题,但我终于找到了最简单的解决方案,它的工作非常好
首先你需要调用这个网址..
HTTP GET:https://www.youtube.com/get_video_info?& video_id = [ video_id] & el = info & ps = default & nerl =& gl = US &hl = zh- CN
并且不要忘记用目标ID更改最后一个id.
- 只需粘贴数据并按几次解码,以确保解码良好
最后搜索一个名为dashmpd的键
或使用此简单解决方案
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);
Run Code Online (Sandbox Code Playgroud)
implementation 'com.github.HaarigerHarald:android-youtubeExtractor:v1.7.0'
Run Code Online (Sandbox Code Playgroud)
您必须从youtube URL(在您的情况下是真实URL)获取HTTP响应,然后搜索"url_encoded_fmt_stream_map"部分.在该部分中,您将获得一个需要解码两次的URI,以获取您正在寻找的DASH URL.
要在 exoplayer 中播放 youtube 视频,我们可以使用这个库
https://github.com/HaarigerHarald/android-youtubeExtractor
Run Code Online (Sandbox Code Playgroud)
只需获取这样的 url,然后在 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);
Run Code Online (Sandbox Code Playgroud)
这是使用的库
implementation 'com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT'
Run Code Online (Sandbox Code Playgroud)
这是基本 url 添加到他们的视频 id
val YouTubeBase="https://www.youtube.com/watch?v="
Run Code Online (Sandbox Code Playgroud)
这是使用的库, 我将使用循环来获取所有视频质量(420,720,180),因为如果视频不包含 1080,则不适用于您,这样我将循环获取所有质量, 但如果发现更高质量,它将选择最佳质量,如果你想获得低质量,你可以通过称为 iTags 的反向数组来编辑它
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)
Run Code Online (Sandbox Code Playgroud)
这是我在上一个项目中的代码,我希望能帮助你使用 Exo 播放器使用库
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
20236 次 |
最近记录: |