【问题标题】:Downloading 3gp Video from Youtube Rtsp URL on Android从 Android 上的 Youtube Rtsp URL 下载 3gp 视频
【发布时间】:2013-09-02 08:43:37
【问题描述】:

我正在尝试从 Youtube 的 rtsp URL 下载 3gp 视频文件并将其保存到我的外部存储中,但我的方法似乎只适用于 HTTP URL。

我收到了这个警告:

09-02 10:32:40.877: WARN/System.err(7988): java.net.MalformedURLException: Unknown protocol: rtsp

我的下载方式如下:

public static void downloadFromURL(String url, File cacheDir, String fileName) throws IOException {
        long startTime = System.currentTimeMillis();
        String TAG = "DL";
        if (url != null) {
            if (fileName.contains("/"))
                fileName = fileName.replace("/", "-");
            url = url.replace(" ", "%20");
            URL mUrl = new URL(url);

            URLConnection ucon = mUrl.openConnection();

            ucon.setReadTimeout(TIMEOUT_CONNECTION);
            ucon.setConnectTimeout(TIMEOUT_SOCKET);

            File f = new File(cacheDir, fileName);
            InputStream is = ucon.getInputStream();
            BufferedInputStream inStream = new BufferedInputStream(is, BUFFER_SIZE);
            FileOutputStream outStream = new FileOutputStream(f);
            byte[] buff = new byte[BUFFER_SIZE];


            int len;
            while ((len = inStream.read(buff)) != -1) {
                outStream.write(buff, 0, len);
            }
            // clean up
            outStream.flush();
            outStream.close();
            inStream.close();

            android.util.Log.d(TAG, "Download completed in " + ((System.currentTimeMillis() - startTime) / 1000) + " sec");
        }
    }

仅供参考,我在带有 Wi-Fi 连接的 Nexus 7 上对其进行了测试。 如果有人能解决我遇到的问题,请告诉我。

更新

无论如何,我找到了这些 Objective-C sn-ps 可以满足我的需求,但我无法将其转换为 Java 代码:

NSString *urlString = @"http://www.youtube.com/get_video_info?&video_id=7ubt8AWa7SU"; //7ubt8AWa7SU gylfmQgtMJc
    NSURL *infoUrl = [NSURL URLWithString:urlString];
    NSError *error = NULL;
    NSString *info = [NSString stringWithContentsOfURL:infoUrl encoding:NSUTF8StringEncoding error:&error];
    if (info == nil)
    {
        NSLog(@"Error: %@", [error description]);
        return;
    }
    NSArray *urlComponents = [info componentsSeparatedByString:@"&"];
    NSArray *itemComponents;
    NSString *urlEncodedFmtStreamMap = NULL;
    for (NSString *item in urlComponents)
    {
        itemComponents = [item componentsSeparatedByString:@"="];
        if (itemComponents)
        {
            NSString *first = [itemComponents objectAtIndex:0];
            if ([first isEqualToString: @"url_encoded_fmt_stream_map"])
            {
                urlEncodedFmtStreamMap = [itemComponents objectAtIndex:1];
                break;
            }
        }
    }
    NSString *type = NULL;
    NSString *urlSeg1 = NULL;
    NSString *sig = NULL;
    if (urlEncodedFmtStreamMap)
    {
        NSArray *formats = [[urlEncodedFmtStreamMap stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] componentsSeparatedByString:@","];
        for (NSString *item in formats)
        {
            type = NULL;
            urlSeg1 = NULL;
            sig = NULL;
            NSArray *pairs = [item componentsSeparatedByString:@"&"];
            for (NSString *pair in pairs)
            {
                NSArray *varComps = [pair componentsSeparatedByString:@"="];
                NSString *varName = [varComps objectAtIndex: 0];
                NSString *varValue = [[varComps objectAtIndex: 1] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
                if ([varName isEqualToString: @"type"])
                {
                    NSArray *typeSegments = [varValue componentsSeparatedByString: @";"];
                    type = [typeSegments objectAtIndex:0];
                }
                else if ([varName isEqualToString: @"url"])
                {
                    urlSeg1 = [varValue stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
                }
                else if ([varName isEqualToString: @"sig"])
                {
                    sig = varValue;
                }
            }
            if ([type isEqualToString:@"video/mp4"] && urlSeg1 && sig)
            {
                self.videoUrl = [[urlSeg1 stringByAppendingString: @"&signature="] stringByAppendingString: sig];
                break;
            }
        }
    }

【问题讨论】:

  • 仅供参考,我知道这在编程方面是题外话,但请查看 youtube.com/static?gl=US&template=terms 的 5B
  • 你在做模拟器吗?
  • @66CLSjY 好吧,根据维基百科“下载意味着从远程系统接收数据到本地系统”。只是“观看”一个 youtube 视频也将被视为下载。当您打开网络浏览器并单击显示“下载”的文字时,它只是下载吗?
  • 您可能会更好地使用 Firefox 中的下载帮助程序扩展,或者将 Firefox 中的下载帮助程序扩展控制为某种 BHO。所有艰苦的工作都已经完成,我希望构建一个包装器而不是重新发明轮子。

标签: android ios android-youtube-api


【解决方案1】:

我认为没有一种简单的方法可以做到这一点。获取 RTSP 流并不像 HTTP GET 请求那么简单。视频和音频数据包作为 RTP 发送,本质上是带有额外数据的 UDP 数据包,然后您有 RTSP 和 RTCP(您可以忽略)用于服务器/客户端通信。

我建议查看 MediaPlayer 和 Stagefright 源代码,尤其是它们设置不同数据源的地方,看看您是否可以提取部分 RTSP 握手和 RTP 会话设置。

【讨论】:

    猜你喜欢
    • 2011-08-08
    • 2011-04-30
    • 2011-11-04
    • 2019-03-06
    • 2010-11-08
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多