Как получить прямую ссылку удаленного видео из встроенного URL в URL в Android с помощью JSoup?

Ранее я задавал вопрос о том, как извлечь встроенный URL для видеофайла, и успешно это сделал. Теперь у меня другая проблема. Ответ json для ответа веб-камеры API WUnderground дает следующий URL:

https://www.wunderground.com/webcams/cadot1/902/show.html

Используя JSoup и в ответ на мою первоначальную проблему, я смог получить эту встроенную ссылку:

https://www.wunderground.com/webcams/cadot1/902/video.html?month=11&year=2016&filename=current.mp4

Пытаясь "передать" видео с этого URL в VideoView, я продолжал получать сообщение об ошибке "не могу воспроизвести видео". Посмотрев на источник по этой ссылке, я заметил, что видеофайл, который нужно воспроизвести, не ссылается на html, а на javascript. Как я могу получить прямую ссылку на видеофайл, который нужно воспроизвести? Используете JSoup или другой процесс?

Источник для URL https://www.wunderground.com/webcams/cadot1/902/video.html?month=11&year=2016&filename=current.mp4 показывает следующее для необходимого видеофайла в <script> скобка:

URL: "//icons.wunderground.com/webcamcurrent/c/a/cadot1/902/current.mp4?e=1480377508"

Я использую JSoup для получения встроенного URL-адреса для видео из URL-адреса ответа следующим образом:

    private class VideoLink extends AsyncTask<Void, Void, Void> {
    String title;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog.setTitle("JSOUP Test");
        mProgressDialog.setMessage("Loading...");
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {

            // for avoiding javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name
            System.setProperty("jsse.enableSNIExtension", "false");

            // WARNING: do it only if security isn't important, otherwise you have
            // to follow this advices: http://stackru.com/a/7745706/1363265
            // Create a trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){
                public X509Certificate[] getAcceptedIssuers(){return null;}
                public void checkClientTrusted(X509Certificate[] certs, String authType){}
                public void checkServerTrusted(X509Certificate[] certs, String authType){}
            }};

            // Install the all-trusting trust manager
            try {
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, trustAllCerts, new SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            } catch (Exception e) {
                ;
            }

            // Connect to the web site
            Document doc = Jsoup.connect(TEST_URL).get();
            Elements elements = doc.getElementsByClass("videoText");
            // Get the html document title
            for (Element link : elements) {
                String linkHref = link.attr("href");
                // linkHref contains something like video.html?month=11&year=2016&filename=current.mp4
                // TODO check if linkHref ends with current.mp4
                title = linkHref;
            }
        } catch (IOException e) {
            e.printStackTrace();
            mProgressDialog.dismiss();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        // Set title into TextView
        resultTxt.setText(title);
        String resVid = TEST_URL;
        Log.d(TAG, "URL: " + resVid);
        Uri resUri = Uri.parse(resVid);
        try {
            // Start the MediaController
            MediaController mediacontroller = new MediaController(
                    MainActivity.this);
            mediacontroller.setAnchorView(resultVidVw);
            // Get the URL from String VideoURL
            Uri video = Uri.parse(resVid);
            resultVidVw.setMediaController(mediacontroller);
            resultVidVw.setVideoURI(video);

        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }

        resultVidVw.requestFocus();
        resultVidVw.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            // Close the progress bar and play the video
            public void onPrepared(MediaPlayer mp) {
                mProgressDialog.dismiss();
                resultVidVw.start();
            }
        });
    }
}

Обратите внимание, что мне нужно сделать это для каждого JSONObject в массиве ответов.

1 ответ

Решение

Вот как вы можете получить файл:

(Обратите внимание: часть Extraction работает только с текущим html-кодом сайта, и если он изменится, он может работать некорректно!)

String url = "https://www.wunderground.com/webcams/cadot1/902/video.html";
int timeout = 100 * 1000;

// Extract video URL
Document doc = Jsoup.connect(url).timeout(timeout).get();
Element script = doc.getElementById("inner-content")
        .getElementsByTag("script").last();
String content = script.data();
int indexOfUrl = content.indexOf("url");
int indexOfComma = content.indexOf(',', indexOfUrl);
String videoUrl = "https:" + content.substring(indexOfUrl + 6, indexOfComma - 1);
System.out.println(videoUrl);

[Выход: https://icons.wunderground.com/webcamcurrent/c/a/cadot1/902/current.mp4?e=1481246112]

Теперь вы можете получить файл, указав .ignoreContentType(true) чтобы избежать org.jsoup.UnsupportedMimeTypeException а также .maxBodySize(0) снять ограничение на размер файла.

// Get video file
byte[] video = Jsoup.connect(videoUrl)
        .ignoreContentType(true).timeout(timeout).maxBodySize(0)
        .execute().bodyAsBytes();

Я не знаю, можете ли вы играть в Android или нет, но я думаю, что вы можете сохранить его, используя org.apache.commons.io.FileUtils (Я тестировал его в Java SE, но не в среде разработки Android.)

// Save video file
org.apache.commons.io.FileUtils.writeByteArrayToFile(new File("test.mp4"), video);
Другие вопросы по тегам