使用三星手机时,流式传输到 VideoView 只能在 Wifi 上播放

发布于 2025-01-01 04:17:54 字数 1554 浏览 1 评论 0原文

我正在使用以下库将 YouTube 视频流式传输到 Android 应用程序。

http: //code.google.com/p/android-youtube-player/source/browse/trunk/OpenYouTubeActivity/src/com/keyes/youtube/OpenYouTubePlayerActivity.java?r=3

我成功了能够通过 3G 和 Wifi 在 HTC 和 Motorola 手机上播放视频。然而,在 Samsung Galaxy (Epic 4G) 和 Samsung Galaxy II 手机上,我只能使用 Wifi 进行游戏。 3G 给我这个错误:“无法播放视频。抱歉,该视频无法播放。”

我尝试过强制使用低质量的 YouTube 流媒体,但这没有帮助。我在日志中看到在这两种情况下(3G/Wifi)都会调用 Start()。这是 VideoView 的问题吗?有解决方法吗?

编辑 2

视频来自 YouTube API。我尝试使用嵌入式流和普通流,以及可用的最低质量流(因视频而异)。另外,我不认为这是编码问题,因为相同的视频可以使用 Wifi 正常播放。

编辑 1

无论视频是使用 Wifi 还是不使用 3G 播放,我也会收到以下输出。

01-30 15:22:38.305: E/MediaPlayer(3831): error (1, -1)
01-30 15:22:38.305: E/MediaPlayer(3831): callback application
01-30 15:22:38.305: E/MediaPlayer(3831): back from callback
01-30 15:22:38.309: E/MediaPlayer(3831): Error (1,-1)

根据这个链接,这些错误意味着以下内容(我认为) :

/*
 Definition of first error event in range (not an actual error code).
 */
const PVMFStatus PVMFErrFirst = (-1);
/*
 Return code for general failure
 */
const PVMFStatus PVMFFailure = (-1);
/*

/*
 Return code for general success
 */
const PVMFStatus PVMFSuccess = 1;
/*

进一步增加混乱。

I am using the following library to stream YouTube videos to an Android application.

http://code.google.com/p/android-youtube-player/source/browse/trunk/OpenYouTubeActivity/src/com/keyes/youtube/OpenYouTubePlayerActivity.java?r=3

I am successfully able to play videos on HTC and Motorola phones over 3G and Wifi. However, on Samsung Galaxy (Epic 4G) and Samsung Galaxy II phones I am only able to play using Wifi. 3G gives me this error: "Cannot play video. Sorry this video cannot be played."

I have tried forcing low quality YouTube streaming, but this did not help. I see in my log that Start() is being called in both cases (3G/Wifi). Is this an issue with VideoView? Is there a workaround?

Edit 2

The videos are coming from YouTube API. I have attempted using embedded and normal streams, as well as lowest quality stream available (varying per video). Also, I do not think it is an encoding issue since the same videos play correctly using Wifi.

Edit 1

I also receive the following output regardless of wether video plays using Wifi or does not using 3G.

01-30 15:22:38.305: E/MediaPlayer(3831): error (1, -1)
01-30 15:22:38.305: E/MediaPlayer(3831): callback application
01-30 15:22:38.305: E/MediaPlayer(3831): back from callback
01-30 15:22:38.309: E/MediaPlayer(3831): Error (1,-1)

According to this Link, these errors means the following (I think):

/*
 Definition of first error event in range (not an actual error code).
 */
const PVMFStatus PVMFErrFirst = (-1);
/*
 Return code for general failure
 */
const PVMFStatus PVMFFailure = (-1);
/*

/*
 Return code for general success
 */
const PVMFStatus PVMFSuccess = 1;
/*

Further adding confusion.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猫腻 2025-01-08 04:17:54

是的,正如您所想,这是 VideoView 中的问题,类似的问题也出现在 MediaPlayer 中,并且我遇到了与您类似且奇怪的问题,我有仅在 3G 而非 Wi-Fi 上播放视频时出现问题。这通常发生在 2.1 和某些 2.2 设备上,但不会发生在我迄今为止所看到的更高 API 级别上。

因此,我可以建议执行以下操作:

首先检查正在运行的设备是否可能存在问题,如下所示:

//Define a static list of known devices with issues
static List sIssueDevices=Arrays.asList(new String[]{"HTC Desire","LG-P500","etc"});

if(Build.VERSION.SDK_INT<9){
     if(sIssueDevices.contains(Build.Device){
         //This device may have issue in streaming, take appropriate actions
     }
}

这是最简单的部分,以检测正在运行的设备在流式传输视频时是否存在问题。现在,我所做的(也可能对您有所帮助)是将来自 Youtube 的视频缓冲在 SDCard 上的一个文件中,并将该文件设置为您的 VideoView 的 source。我将编写一些代码片段来看看我的方法是怎样的:

private class GetYoutubeFile extends Thread{
    private String mUrl;
    private String mFile;
    public GetYotubeFile(String url,String file){
        mUrl=url;
        mFile=file;
    }

    @Override
    public void run() {
        super.run();
        try {

            File bufferingDir=new File(Environment.getExternalStorageDirectory()
                    +"/YoutubeBuff");

            File bufferFile=new File(bufferingDir.getAbsolutePath(), mFile);
            //bufferFile.createNewFile();
            BufferedOutputStream bufferOS=new BufferedOutputStream(
                                      new FileOutputStream(bufferFile));

            URL url=new URL(mUrl);
            URLConnection connection=url.openConnection();
            connection.setRequestProperty("User-Agent", "Mozilla");
            connection.connect();
            InputStream is=connection.getInputStream();
            BufferedInputStream bis=new BufferedInputStream(is,2048);

            byte[] buffer = new byte[16384];
            int numRead;
            boolean started=false;
            while ((numRead = bis.read(buffer)) != -1 && !mActivityStopped) {
                //Log.i("Buffering","Read :"+numRead);
                bufferOS.write(buffer, 0, numRead);
                bufferOS.flush();
                mBuffPosition += numRead;
                if(mBuffPosition>120000 &&!started){
                    Log.e("Player","BufferHIT:StartPlay");
                    setSourceAndStartPlay(bufferFile);
                    started=true;
                }

            }
            Log.i("Buffering","Read -1?"+numRead+" stop:"+mActivityStopped);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public void setSourceAndStartPlay(File bufferFile) {
    try {
        mPlayer.setVideoPath(bufferFile.getAbsolutePath());
        mPlayer.prepare();
        mPlayer.start();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

VideoView 在文件结束之前停止播放时,会出现另一个问题,因为文件中没有足够的缓冲。为此,您需要设置一个 onCompletionListener() ,如果您没有到达视频末尾,则应该从最后一个位置重新开始视频播放:

public void onCompletion(MediaPlayer mp) {
    mPlayerPosition=mPlayer.getCurrentPosition();
    try {
        mPlayer.reset();
        mPlayer.setVideoPath(
             new File("mnt/sdcard/YoutubeBuff/"+mBufferFile).getAbsolutePath());
        mPlayer.seekTo(mPlayerPosition);
        mPlayer.start();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

最后,当然 GetYoutubeFile 线程在 onCreate() 方法中启动:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //init views,player,etc
    new GetYoutubeFile().start();
}

我认为必须对此代码进行一些修改和调整,这可能不是最好的方法,但它有所帮助我,我找不到任何 选择。

Yes, as you are thinking, this is a issue in VideoView, similar issues also appear in MediaPlayer, and I've encountered similar and strange issues as you did, I had problems when the video was played only on 3G and not on Wi-Fi. This usually happens on 2.1 and some 2.2 devices, but not on higher API levels as I've seen so far.

So what I can recommend is do the following :

First check if the running device may be one that can have issues, something like this :

//Define a static list of known devices with issues
static List sIssueDevices=Arrays.asList(new String[]{"HTC Desire","LG-P500","etc"});

if(Build.VERSION.SDK_INT<9){
     if(sIssueDevices.contains(Build.Device){
         //This device may have issue in streaming, take appropriate actions
     }
}

So this was the simplest part, to detect if the running device may have issues in streaming the video. Now, what I did and may also help you, is buffer the video from Youtube in a file on the SDCard and set that file as the source for your VideoView. I will write some code snippets to see how my approach was :

private class GetYoutubeFile extends Thread{
    private String mUrl;
    private String mFile;
    public GetYotubeFile(String url,String file){
        mUrl=url;
        mFile=file;
    }

    @Override
    public void run() {
        super.run();
        try {

            File bufferingDir=new File(Environment.getExternalStorageDirectory()
                    +"/YoutubeBuff");

            File bufferFile=new File(bufferingDir.getAbsolutePath(), mFile);
            //bufferFile.createNewFile();
            BufferedOutputStream bufferOS=new BufferedOutputStream(
                                      new FileOutputStream(bufferFile));

            URL url=new URL(mUrl);
            URLConnection connection=url.openConnection();
            connection.setRequestProperty("User-Agent", "Mozilla");
            connection.connect();
            InputStream is=connection.getInputStream();
            BufferedInputStream bis=new BufferedInputStream(is,2048);

            byte[] buffer = new byte[16384];
            int numRead;
            boolean started=false;
            while ((numRead = bis.read(buffer)) != -1 && !mActivityStopped) {
                //Log.i("Buffering","Read :"+numRead);
                bufferOS.write(buffer, 0, numRead);
                bufferOS.flush();
                mBuffPosition += numRead;
                if(mBuffPosition>120000 &&!started){
                    Log.e("Player","BufferHIT:StartPlay");
                    setSourceAndStartPlay(bufferFile);
                    started=true;
                }

            }
            Log.i("Buffering","Read -1?"+numRead+" stop:"+mActivityStopped);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public void setSourceAndStartPlay(File bufferFile) {
    try {
        mPlayer.setVideoPath(bufferFile.getAbsolutePath());
        mPlayer.prepare();
        mPlayer.start();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Another issue will arise when the VideoView has stopped playing before the end of file, because not enough was buffered in the file. For this you need to set an onCompletionListener() and if you are not at the end of the video, you should start again the video playback from the last position :

public void onCompletion(MediaPlayer mp) {
    mPlayerPosition=mPlayer.getCurrentPosition();
    try {
        mPlayer.reset();
        mPlayer.setVideoPath(
             new File("mnt/sdcard/YoutubeBuff/"+mBufferFile).getAbsolutePath());
        mPlayer.seekTo(mPlayerPosition);
        mPlayer.start();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

In the end, of course the GetYoutubeFile thread is started in the onCreate() method :

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //init views,player,etc
    new GetYoutubeFile().start();
}

Some modifications and adaptation I think will have to be done for this code, and it may not be the best approach, but it helped me, and I couldn't find any alternative.

爱你不解释 2025-01-08 04:17:54

我已经用自己的方式解决了这个问题。首先,每次阅读你的日志猫。如果你得到了

Error (1,-1) 

这个,意味着你会得到抱歉,该视频无法播放消息。所以在这种情况下完成该活动,提供自定义进度条并下载视频。下载后将其保存在临时文件夹中然后播放。播放后删除该文件夹。

阅读 log cat---

 try {
  Process process = Runtime.getRuntime().exec("logcat -d");
  BufferedReader bufferedReader = new BufferedReader(
  new InputStreamReader(process.getInputStream()));
   StringBuilder log=new StringBuilder();
  String line;
  while ((line = bufferedReader.readLine()) != null) {
    log.append(line);
  }
} catch (IOException e) {
}

也阅读这个答案。虽然这只是与应用程序无关的用户体验。但有时在默认应用程序中也会发生这种情况

大量视频,即使我有完整的 3G 网络覆盖,也会说“对不起,该视频无法播放”。有一天,我对此非常生气,我只是一直按“确定”来忽略该消息,然后再次按视频,却再次看到“抱歉,该视频无法播放”消息。我重复了这个过程(在我盲目的愤怒中),但最终,经过大约 5 次尝试,视频奇迹般地播放了!

这个方法几乎每次都对我有效。大多数视频第一次都不想播放,但最终如果我坚持不懈,并继续告诉它播放,即使它告诉我它“不能”播放视频,它也会播放!不过,有些视频我必须按“确定”、按视频、按“确定”、按视频等等......大约 20 次才真正决定播放。那些时候,我几乎差点把手机扔到地板上,因为我对 YouTube 无法使用感到非常沮丧。

我希望有一种方法可以解决这个问题。似乎没有人想出解决办法。每个人都只是说“哦,是的,我有同样的问题”,但没有人做出任何贡献。谷歌,在您的手机上解决这个问题。这似乎正在全球范围内的各种 Android 手机上发生。

I have tackle with this problem in my own way.First every time read your log cat.If you got

Error (1,-1) 

that means you will get sorry,this video can not play message.So in this case finish that activity, give custom progress bar and download video.Then after downloading save it in temporary folder then play it.After playing delete that folder.

To reading log cat---

 try {
  Process process = Runtime.getRuntime().exec("logcat -d");
  BufferedReader bufferedReader = new BufferedReader(
  new InputStreamReader(process.getInputStream()));
   StringBuilder log=new StringBuilder();
  String line;
  while ((line = bufferedReader.readLine()) != null) {
    log.append(line);
  }
} catch (IOException e) {
}

Read this answer too. although it is just user experience not linked to app.but it happens sometimes in default application also

Heaps of videos, even if I have full 3G network coverage, will say "Sorry, this video cannot be played". One day, I got so pissed off with it, I just kept pressing 'Okay' to dismiss the message, and then pressed the video again only to see the "Sorry, this video cannot be played" message again. I repeated this process (in my blind anger), but eventually, after about 5 tries, the video decided to miraculously play!

This method pretty much works for me every time. Most videos won't want to play the first time, but eventually if I am just persistent, and keep telling it to play even though it tells me it 'can't' play the video, it will play! Although, some videos i've had to press 'Okay', press the video, press 'Okay', press the video etc... for like 20 times before it actually decided to play. Those times, I have been incredibly close to getting my phone and throwing it down on the floor because of how shitty I am with how youtube won't work.

I wish there was a way to fix this problem. No one seems to have come up with a solution. Everyone just says "oh yeah I have the same problem" but no one contributes anything. GOOGLE, SOLVE THIS PROBLEM ON YOUR PHONES. THIS SEEMS TO BE HAPPENING WORLDWIDE, ON A RANGE OF ANDROID PHONES.

我乃一代侩神 2025-01-08 04:17:54

此消息通常来自视频编码不正确(“无法播放视频。抱歉,该视频无法播放。”)我在 videoview 上苦苦挣扎了一段时间,现在,即使使用 Wifi,所有测试的设备上也能播放正确编码的视频或 3G。如果您想知道如何对视频进行编码,请告诉他们。为了流式传输视频,我使用了 android sdk api 的演示,它工作完美。

This message often cames from the inappropriate encoding of the video ("Cannot play video. Sorry this video cannot be played.") I was struggling with videoview for a while , now the correct encoded videos play on all tested devices, even when using Wifi or 3G. Let em know if you want to know how to encode the videos. And for streaming the videos I used the demo from android sdk apis and it works flawless.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文