Немного поздно, но я думаю, что это хороший вопрос, и на него пока нет хорошего ответа.
Если вы хотите транслировать камеру и микрофон с устройства Android, у вас есть две основные альтернативы: реализации Java или NDK.
Реализация Java.
Я только собираюсь упомянуть эту идею, но в основном она реализует RTSP-сервер и протокол RTP в Java на основе этих стандартов. Протокол потоковой передачи в реальном времени версии 2.0 и Формат полезной нагрузки RTP для Видео H.264 . Это задание будет очень долгим и сложным. Но если вы делаете свой PhP, было бы неплохо иметь хорошую RTSP Java lib для Android.
Реализация NDK.
Это альтернатива, включающая различные решения. Основная идея - использовать мощную библиотеку C или C ++ в нашем приложении для Android. Для этого экземпляра FFmpeg. Эта библиотека может быть скомпилирована для Android и может поддерживать различные архитектуры.
Проблема этого подхода в том, что вам может потребоваться узнать об Android NDK, C и C ++, чтобы выполнить это.
Но есть альтернатива. Вы можете обернуть библиотеку c и использовать FFmpeg. Но как?
Например, используя FFmpeg Android , который был скомпилирован с x264, libass, fontconfig, freetype и fribidi и поддерживает различные архитектуры. Но все равно сложно запрограммировать, если вы хотите осуществлять потоковую передачу в реальном времени, вам нужно иметь дело с файловыми дескрипторами и входными / выходными потоками.
Лучшей альтернативой с точки зрения программирования на Java является использование JavaCV . JavaCV использует оболочки из обычно используемых библиотек компьютерного зрения, которые включают в себя: ( OpenCV , FFmpeg и т. Д., И предоставляет служебные классы, облегчающие использование их функций на платформе Java, в том числе ( конечно) Android.
JavaCV также поставляется с аппаратным ускорением полноэкранного отображения изображений (CanvasFrame
и GLCanvasFrame
), простыми в использовании методами для параллельного выполнения кода на нескольких ядрах (Parallel
), удобной для пользователя геометрической и цветной калибровка камер и проекторов (GeometricCalibrator
, ProCamGeometricCalibrator
, ProCamColorCalibrator
), обнаружение и сопоставление характерных точек (ObjectFinder
), набор классов, которые реализуют прямое выравнивание изображения систем проектор-камера (в основном GNImageAligner
) , ProjectiveTransformer
, ProjectiveColorTransformer
, ProCamTransformer
и ReflectanceInitializer
), пакет анализа BLOB-объектов (Blobs
), а также различные функции в классе JavaCV
. Некоторые из этих классов также имеют аналог OpenCL и OpenGL, имена которых заканчиваются на CL
или начинаются с GL
, т. Е. JavaCVCL
, GLCanvasFrame
и т. Д.
Но как мы можем использовать это решение?
Здесь мы имеем базовую реализацию для потоковой передачи с использованием UDP.
String streamURL = "udp://ip_destination:port";
recorder = new FFmpegFrameRecorder(streamURL, frameWidth, frameHeight, 1);
recorder.setInterleaved(false);
// video options //
recorder.setFormat("mpegts");
recorder.setVideoOption("tune", "zerolatency");
recorder.setVideoOption("preset", "ultrafast");
recorder.setVideoBitrate(5 * 1024 * 1024);
recorder.setFrameRate(30);
recorder.setSampleRate(AUDIO_SAMPLE_RATE);
recorder.setVideoCodec(AV_CODEC_ID_H264);
recorder.setAudioCodec(AV_CODEC_ID_AAC);
Эта часть кода показывает, как инициализировать объект FFmpegFrameRecorder, называемый рекордером. Этот объект будет захватывать и кодировать кадры, полученные с камеры, и сэмплы, полученные с микрофона.
Если вы хотите захватить предварительный просмотр в том же приложении Android, то нам нужно реализовать класс CameraPreview, который будет преобразовывать необработанные данные, передаваемые с камеры, и создавать предварительный просмотр и фрейм для FFmpegFrameRecorder.
Не забудьте заменить ip_destination на ip компьютера или устройства, на которое вы хотите отправить поток. Порт может быть 8080 в качестве примера.
@Override
public Mat onCameraFrame(Mat mat)
{
if (audioRecordRunnable == null) {
startTime = System.currentTimeMillis();
return mat;
}
if (recording && mat != null) {
synchronized (semaphore) {
try {
Frame frame = converterToMat.convert(mat);
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
recorder.record(frame);
} catch (FFmpegFrameRecorder.Exception e) {
LogHelper.i(TAG, e.getMessage());
e.printStackTrace();
}
}
}
return mat;
}
Этот метод показывает реализацию метода onCameraFrame
, который получает мат (изображение) с камеры, и он преобразуется в кадр и записывается объектом FFmpegFrameRecorder.
@Override
public void onSampleReady(ShortBuffer audioData)
{
if (recorder == null) return;
if (recording && audioData == null) return;
try {
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
LogHelper.e(TAG, "audioData: " + audioData);
recorder.recordSamples(audioData);
} catch (FFmpegFrameRecorder.Exception e) {
LogHelper.v(TAG, e.getMessage());
e.printStackTrace();
}
}
Как и в случае со звуком, audioData
- это объект ShortBuffer
, который будет записан FFmpegFrameRecorder.
На ПК или на устройстве вы можете запустить следующую команду для получения потока.
ffplay udp://ip_source:port
ip_source
- это ip-адрес смартфона, который передает потоковое видео с камеры и микрофона. Порт должен быть таким же 8080.
Я создал решение в своем репозитории github здесь: UDPAVStreamer .
Удачи