如何从 android 的视频视图中显示的 ip 摄像头的流式视频中捕获图像

Posted

技术标签:

【中文标题】如何从 android 的视频视图中显示的 ip 摄像头的流式视频中捕获图像【英文标题】:How to capture image from a streaming video of ip camera that shown in video view in android 【发布时间】:2014-12-24 04:38:20 【问题描述】:

我想问如何通过我的应用程序中的视频视图布局从我的应用程序中显示的网络摄像机的流式视频中捕获图像,当我单击一个按钮时,它将捕获视频视图中显示的图像。我使用 rtsp 协议 ip 摄像头..

package com.javacodegeeks.androidvideoviewexample;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.MediaController;
import android.widget.VideoView;

public class AndroidVideoViewExample extends Activity 

    private VideoView myVideoView;
    private int position = 0;
    private ProgressDialog progressDialog;
    private MediaController mediaControls;

    @Override
    protected void onCreate(final Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        // Get the layout from video_main.xml
        setContentView(R.layout.activity_main);

        if (mediaControls == null) 
            mediaControls = new MediaController(AndroidVideoViewExample.this);
        

        // Find your VideoView in your video_main.xml layout
        myVideoView = (VideoView) findViewById(R.id.video_view);

        // Create a progressbar
        progressDialog = new ProgressDialog(AndroidVideoViewExample.this);
        // Set progressbar title
        progressDialog.setTitle("JavaCodeGeeks Android Video View Example");
        // Set progressbar message
        progressDialog.setMessage("Loading...");

        progressDialog.setCancelable(false);
        // Show progressbar
        progressDialog.show();

        try 

            myVideoView.setMediaController(mediaControls);
            myVideoView.setVideoURI(Uri.parse("rtsp://192.168.2.12/user=admin&password=&channel=1&stream=0.sdp?"));

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

        myVideoView.requestFocus();
        myVideoView.setOnPreparedListener(new OnPreparedListener() 
            // Close the progress bar and play the video
            public void onPrepared(MediaPlayer mp) 
                progressDialog.dismiss();
                myVideoView.seekTo(position);
                if (position == 0) 
                    myVideoView.start();
                 else 
                    myVideoView.pause();
                
            
        );

    

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) 
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putInt("Position", myVideoView.getCurrentPosition());
        myVideoView.pause();
    

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) 
        super.onRestoreInstanceState(savedInstanceState);
        position = savedInstanceState.getInt("Position");
        myVideoView.seekTo(position);
    

这是我在这个小组中找到的编码,它工作得非常好......现在我想添加一个按钮来捕捉图像,

我发现我们可以使用 mediadataretriever 方法并将其保存到 sd 卡? 这是真的吗?

【问题讨论】:

您可以通过编程方式截取屏幕截图并将其裁剪并保存到卡片中 谢谢你的回答@Shink,我想把它留作最后一张纸牌,你有什么办法吗? 【参考方案1】:

您也可以尝试使用 cgi 服务以另一种方式捕获图像,例如 dahua IPC-HDW2231T-AS-S2 提供的服务。

http://CAM-IP/cgi-bin/snapshot.cgi

在我的例子中,我使用它来调用快照创建并自动将其存储在 ftp 服务器上,但如果你想从请求中获取图像,规则将是相同的。

要发出请求而不获得 401 - 未经授权的结果代码,您必须实现 摘要式身份验证。您可以自行完成,也可以像我一样使用 bare-bones-digest 依赖项。

然后您可以制作 AsyncTask 类使其异步(以下示例在 kotlin 中)

class RequestTask :
        AsyncTask<String?, String?, Boolean?>() 
        override fun doInBackground(vararg params: String?): Boolean?             
            // Step 1. Create the connection
            val url = URL(params[0])
            var connection =
                url.openConnection() as HttpURLConnection

            // Step 2. Make the request and check to see if the response contains an authorization challenge
            if (connection.responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) 
                // Step 3. Create a authentication object from the challenge...
                val auth: DigestAuthentication = DigestAuthentication.fromResponse(connection)
                // ...with correct credentials
                auth.username(username).password(password)

                // Step 4 (Optional). Check if the challenge was a digest challenge of a supported type
                if (!auth.canRespond()) 
                    // No digest challenge or a challenge of an unsupported type - do something else or fail
                    return false
                

                // Step 5. Create a new connection, identical to the original one...
                connection = url.openConnection() as HttpURLConnection
                // ...and set the Authorization header on the request, with the challenge response
                connection.setRequestProperty(
                    DigestChallengeResponse.HTTP_HEADER_AUTHORIZATION,
                    auth.getAuthorizationForRequest("GET", connection.url.path)
                )
            

            connection.connect() //there you can also get inputStream from connection for local store of snapshot
            val responseCode = connection.responseCode
            val cLength = connection.contentLength         
            return responseCode == 200
        
    

并执行使用:

RequestTask().execute("http://$CAM-IP/cgi-bin/snapshot.cgi")

如果您遇到Cleartext HTTP traffic not permitted 错误,请参阅that 寻求帮助。

【讨论】:

以上是关于如何从 android 的视频视图中显示的 ip 摄像头的流式视频中捕获图像的主要内容,如果未能解决你的问题,请参考以下文章

如何从android中录制的视频中获取视频名称?

使用视频视图的 Android 视频流(视频视图不自动显示)

当在视频视图android中使用seekbar时如何举杯?

在视频视图中显示按钮

如何通过 URL 的视频视图知道视频在 android VideoView 中启动的实时时间?

如何在android中设计具有弯曲边缘的视频视图?