如何在录制时发送 mp4 的可读部分

Posted

技术标签:

【中文标题】如何在录制时发送 mp4 的可读部分【英文标题】:How to send readable part of mp4 while recording it 【发布时间】:2017-02-23 17:28:27 【问题描述】:

我正在开发一个在后台录制视频并通过读取字节并将其存储在字节数组中的部分发送到服务器的应用程序。现在算法很简单:

    开始录制; 将部分视频文件读入字节数组; 通过 POST 发送字节数组(借助改造)。

如果连接以某种方式中断并且最后一部分未发送,则会出现问题。服务器无法制作可读的视频文件,因为只有在录制停止后才会写入 moov atom。我的问题 - 是否有可能从字节数组部分或任何其他方式制作完整的视频文件?如果可以解决问题,我可以更改视频编解码器。 p.s.我只能通过 POST 发送数据。 p.p.s 我无法更改服务器端的某些内容,包括直接将视频流式传输到服务器。

【问题讨论】:

不要使用 MP4。使用 flv、webm、ts 或碎片化 MP4 感谢您的回答,但我怎样才能做出适当的分割,例如 webm。还有一个问题 - 如何配置 mediarecorder 来录制碎片化的 mp4? 【参考方案1】:

解决方案

我决定以递归方式录制一小段视频。下一个解决方案适用于 Camera API 的第一个版本。如果您使用的是 Camera2 或其他东西 - 您可以尝试使用相同的算法。

在录制视频的服务类中,确保按以下方式配置 mediarecorder:

    mediaRecorder.setMaxDuration(10000);
    //or
    mMediaRecorder.setMaxFileSize(10000);

那么接下来需要实现setOnInfoListener接口:

mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() 
                @Override
                public void onInfo(MediaRecorder mr, int what, int extra) 
                    if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) 
                            //Use next condition if you decided to use max file size
                           //if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED)

                            stopRecording();
                            setRecordingStatus(false);
                            startRecording(surfaceHolder);
                        
                    
                );

不要忘记为下一次迭代传递 surfaceHolder 实例,否则您可能会收到“应用程序丢失表面”错误。 接下来你需要做的是在 onCreate 方法中声明 FileObserver:

FileObserver fileObserver = new FileObserver(pathToFolder, FileObserver.CLOSE_WRITE) 
//FileObserver.CLOSE_WRITE mask means that this observer would be triggered when it receive end of writing to file system event
            @Override
            public void onEvent(int event, String path) 
                //here path is name of file (with extension) but not the full path to file
                    if (event == FileObserver.CLOSE_WRITE && path.endsWith(".mp4")) 
                    String name = String.valueOf(Long.parseLong(path.substring(0, path.length() - 4)) / 1000);
                    sendNewVideo(pathToFolder + "/" + path, name);
                

            
;

在 onStartCommand 方法中:

fileObserver.startWatching();

【讨论】:

这似乎对我们有用,但相机在保存视频片段时停止录制。有什么解决方案吗? 停止录制时检查是否释放相机

以上是关于如何在录制时发送 mp4 的可读部分的主要内容,如果未能解决你的问题,请参考以下文章

如何使来自 iOS 应用程序的 MP4 录制视频可在 Chrome 上播放?

在 mp4 中使用 gstreamer h264 + aac 录制只会产生部分可播放的文件

如何以人类可读的格式输出(到日志)多级数组?

在android中录制视频时如何在视频上绘图,并保存视频和绘图?

如何在 C/C++ 中通过 TCP 发送 .mp4 文件?

mediarecorder 如何暂停和恢复录制视频