这不仅仅是一个问题,更是我尝试解决其中一个最具挑战性功能的展示。 我使用 libstreaming 库将实时视频流到 Wowza Server 并同时需要在SD卡中记录它。 下面我将呈现我所有尝试的过程,并希望从社区中获得新的想法。
从libstreaming流复制字节到mp4文件
开发
我们在libstreaming库中创建了一个拦截器,以将所有发送的字节复制到mp4文件中。Libstreaming通过LocalSocket将字节发送到Wowza服务器。 它使用MediaRecorder访问设备的摄像机和麦克风,并将输出文件设置为LocalSocket的输入流。 我们所做的就是在此输入流周围创建一个扩展自InputStream的包装器,并在其中创建一个File输出流。 因此,每次libstreaming执行LocaSocket输入流上的读取操作时,我们都会将所有数据复制到输出流中,尝试创建有效的MP4文件。
障碍
当我们尝试读取文件时,它是损坏的。 我们意识到MP4文件缺少元信息。 具体来说是moov原子。 我们尝试延迟流的关闭以便有时间发送此头文件(这仍然是猜测),但它没有起作用。 为了测试这些数据的一致性,我们使用一个付费软件来尝试恢复视频,包括标头。 它变得可播放了,但大多数是绿屏。 因此,这成为一个不可靠的解决方案。 我们还尝试使用“untrunc”,这是一个免费的开源命令行程序,由于没有moov原子,它甚至无法启动恢复。
使用编译到Android的ffmpeg访问相机
开发
FFMPEG有一个Gradle插件,带有Java接口,可以在Android应用程序中使用它。我们认为可以通过命令行访问相机(可能在"/dev/video0"中),并将其发送到媒体服务器。
障碍
当尝试访问相机时,我们遇到了“权限被拒绝”的错误。解决方法是root设备以获得访问权,但这会导致电话失去保修,并可能变砖。
使用编译到Android的FFMPEG结合MediaRecorder
开发
我们尝试让FFMPEG通过MediaRecorder流传内部正在录制的mp4文件。
障碍
FFMPEG无法流式传输尚未完成录制的MP4文件。
使用编译到Android的FFMPEG与libstreaming
开发
Libstreaming使用LocalServerSocket作为应用程序和服务器之间的连接,因此我们认为可以使用连接到LocalServerSocket本地地址的FFMPEG将流直接复制到SD卡内的本地文件中。在流开始后,我们还运行了FFMPEG命令来开始将数据记录到文件中。使用FFMPEG,我们相信它会以正确的方式创建一个MP4文件,也就是说包括moov原子头。
障碍
所创建的地址作为手机内部的本地地址无法通过命令行读取,因此无法复制。
使用OpenCV
开发
OpenCV是一个开源跨平台库,提供用于计算机视觉实验和应用程序的构建块。它提供高级接口用于捕获、处理和呈现图像数据。它有自己的API与设备相机连接,因此我们开始研究它,看它是否具有同时流传和记录所需的功能。
障碍
我们发现该库并没有真正定义用于此目的,而更多是用于图像数学处理。我们甚至得到了使用libstreaming(我们已经在使用)的建议。
使用Kickflip SDK
开发
Kickflip是一种媒体流服务,为Android和IOS开发提供自己的SDK。它还使用了较新的HLS协议,而不是RTMP。
障碍
他们的SDK要求我们创建一个占据设备整个屏幕的相机视图Activity,破坏了我们应用程序的可用性。
使用Adobe Air
开发
我们开始咨询Play Store中已经有流向服务器的应用程序的其他开发人员。
障碍
与这些开发人员联系后,他们保证使用此技术同时录制和流式传输将不可能。而且,我们将不得不从头开始重做整个应用程序,使用Adobe Air。
更新
Webrtc
开发
我们开始使用WebRTC,参考这个伟大的项目。我们在NODEJS服务器中包含了信令服务器,并开始通过socket进行标准握手。我们仍在使用本地录制和通过webrtc进行流式传输。
障碍
WebRTC不能在所有网络配置中工作。除此之外,相机采集都是本地代码,这使得尝试复制字节或拦截它更加困难。