从dji无人机到本地服务器的实时流传输的最佳设置是什么?

问题描述 投票:0回答:1

我需要使用Android Mobile SDK将实时视频数据从DJI无人机流式传输到本地服务器。来自服务器的视频数据将由其他软件处理(人为识别)。建议采用什么方法来证明最佳流质量?我们使用Mavic 2进行开发,并使用Matrice 210 v2 RTK进行生产。因此,答案应该主要集中在Matrice 210 v2 RTK的可能性上。

此刻,我们像这样使用DJI Livestreammanager

DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl( rtmpURL );
DJISDKManager.getInstance().getLiveStreamManager().startStream(); 

我们使用带有rtmp模块的nginx Web服务器作为流终结点,该终结点将流推送到网络并同时将流记录到磁盘。这行得通,但是我们看到这些流的质量很差。溪流经常滞后,并且在无人机运动较快时会出现像素。

由于我不熟悉视频处理,因此我需要建议如何解决此要求。我的问题是:-我需要使用ffmpeg库以某种方式预处理流吗?-对于后端服务器,是否有比nginx + rtmp模块更好的解决方案?-是否可以利用矩阵遥控器的输出来提供更高的质量?

dji-sdk
1个回答
0
投票

-我需要使用ffmpeg库以某种方式预处理流吗?

如果您想自己处理流,则需要使用ffmpeg将原始实时流解码为实际的图片帧。请参阅我对问题3的回答。

-对于后端服务器,是否有比nginx + rtmp模块更好的解决方案?

这在很大程度上取决于用例。如果您对视频质量不满意,最好使用ffmpeg自己解码流。我实际上不知道nginx + rtmp会自动执行多少,因为我从未使用过它。

-可以利用矩阵式遥控器的输出来提供更高的质量吗?

可通过SDK访问的原始实时流是原始的h264或h265流(NAL单元,取决于所使用的无人机型号。

在我的应用程序中,我使用摄像机componentKey在onComponentChange方法中注册了VideoDataCallback,并通过LocalBroadcastManager将其发送出去。然后,只需订阅广播,即可在应用程序中的任何位置访问实时流。

private VideoFeeder.VideoDataListener videoDataCallback = (videoBuffer, size) -> {
        Intent intent = new Intent("videoStream");
        intent.putExtra("content", videoBuffer);
        intent.putExtra("size", size);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    };

通过网络发送实时流的一种简单方法是使用TCP-Socket:启动线程并使用IP和端口打开Socket:

this.s = new Socket(this.ipAddress, this.port);
this.s.setKeepAlive(true);
this.s.setTcpNoDelay(true);
this.dos = new DataOutputStream(this.s.getOutputStream());

如果连接/发送失败,则放置一个循环以重新连接它。在BroadcastReceiver中,通过分析大小来累积字节(bos是一个简单的ByteArrayOutputStream):

private BroadcastReceiver frameReceiverNAL = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
        try {
            int frameSize = intent.getIntExtra("size", 0);

            if(frameSize == 2032) {
                bos.write(intent.getByteArrayExtra("content"), 0, frameSize);
            } else {
                bos.write(intent.getByteArrayExtra("content"), 0, frameSize);
                final byte[] sendUnit = bos.toByteArray();
                bos.reset();
                if(numAsyncTasks < MAX_NUMBER_ASYNCTASKS) {
                    numAsyncTasks++;
                    AsyncTask.execute(() -> sendNAL(sendUnit));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        }
    };

private void sendNAL(byte[] sendUnit){
        try {
            if(dos != null) {
                dos.write(sendUnit);
                dos.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        numAsyncTasks--;
    }

MAX_NUMBER_ASYNCTASKS用作上限,以防止应用无法以足够快的速度发送NAL时崩溃(导致崩溃前产生500多个未完成的AsyncTask)。就我而言,我将数字设置为128。

在服务器端,您需要创建一个ServerSocket来接收byteStream。根据编程语言的不同,您可以直接使用ffmpeg,也可以使用本机接口,例如bytedeco从流创建帧。

[另一种方法是将智能手机上的流解码为YUV图像(每个2.8MB),并可选地将它们转换为jpeg,以减小单个帧的大小(每个〜100KB)。然后可以使用TCP套接字将YUV或jpeg图像发送到服务器。 SDK提供了一种在类DJICodecManager中创建YUV图像的方法,并且教程中包含将其转换为JPEG的示例。

© www.soinside.com 2019 - 2024. All rights reserved.