Как отправить читаемую часть mp4 во время его записи

#android #post #video #send #mediarecorder

#Android #Публикация #Видео #Отправить #mediarecorder

Вопрос:

Я работаю над приложением, которое записывает видео в фоновом режиме и отправляет его на сервер по частям, считывая байты и сохраняя их в байтовом массиве. На данный момент алгоритм довольно прост:

  1. начать запись;
  2. чтение части видеофайла в байтовый массив;
  3. отправьте массив байтов по почте (с помощью дооснащения).

Проблема возникает, если соединение каким-то образом прерывается и последняя часть не отправляется. Сервер просто не может создать читаемый видеофайл, так как moov atom будет записан только после остановки записи. Мой вопрос — возможно ли каким-то образом создавать полные видеофайлы из частей байтового массива или любым другим способом? Я могу изменить видеокодек, если это решит проблему. p.s. Я могу отправлять данные только через POST. p.p.s Я не могу что-то изменить на стороне сервера, включая потоковое видео непосредственно на сервер.

Комментарии:

1. Не используйте MP4. Используйте flv, webm, ts или фрагментированный MP4

2. Спасибо за ответ, но как я могу сделать соответствующий разрез, например, 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 для следующей итерации, иначе вы можете получить ошибку «Приложение потеряло поверхность».
Следующее, что вам нужно сделать, это объявить FileObserver в методе onCreate:

 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 amp;amp; path.endsWith(".mp4")) {
                    String name = String.valueOf(Long.parseLong(path.substring(0, path.length() - 4)) / 1000);
                    sendNewVideo(pathToFolder   "/"   path, name);
                }

            }
};
 

В методе onStartCommand:

 fileObserver.startWatching();
 

Комментарии:

1. Похоже, это сработало для нас, но камера прекращает запись во время сохранения фрагментов видео. Какие-либо решения для этого?

2. Проверьте, отпускаете ли вы камеру при остановке записи