Etwas spät, aber ich denke, das ist eine gute Frage, auf die es noch keine gute Antwort gibt.
Wenn Sie die Kamera und das Mikrofon von einem Android-Gerät streamen möchten, haben Sie zwei Möglichkeiten: Java- oder NDK-Implementierungen.
- Java-Implementierung.
Ich werde nur die Idee erwähnen, aber im Grunde geht es darum, einen RTSP-Server und ein RTP-Protokoll in Java zu implementieren, das auf diesen Standards basiert Echtzeit-Streaming-Protokoll Version 2.0 y RTP-Nutzdatenformat für H.264-Video . Diese Aufgabe wird sehr lang und hart sein. Aber wenn Sie Ihre PhP tun, könnte es schön sein, eine schöne RTSP Java lib für Android zu haben.
- NDK-Implementierung.
Diese Alternative umfasst verschiedene Lösungen. Die Hauptidee ist, eine leistungsstarke C- oder C++-Bibliothek in unserer Android-Anwendung zu verwenden. In diesem Fall ist das FFmpeg. Diese Bibliothek kann für Android kompiliert werden und kann verschiedene Architekturen unterstützen. Das Problem bei diesem Ansatz ist, dass Sie sich möglicherweise mit dem Android NDK, C und C++ vertraut machen müssen, um dies zu erreichen.
Aber es gibt eine Alternative. Sie können die C-Bibliothek einpacken und FFmpeg verwenden. Aber wie?
Zum Beispiel mit FFmpeg Android , das mit x264, libass, fontconfig, freetype und fribidi kompiliert wurde und verschiedene Architekturen unterstützt. Aber es ist immer noch schwer zu programmieren, wenn man in Echtzeit streamen will, muss man sich mit Dateideskriptoren und In/Out-Streams beschäftigen.
Die beste Alternative aus Sicht der Java-Programmierung ist die Verwendung von JavaCV . JavaCV verwendet Wrapper von häufig verwendeten Bibliotheken der Computer Vision, die umfasst: ( OpenCV , FFmpeg usw., und bietet Dienstleistungsklassen, um ihre Funktionalität auf der Java-Plattform, einschließlich (natürlich) Android, einfacher zu nutzen.
JavaCV bietet auch eine hardwarebeschleunigte Vollbildanzeige ( CanvasFrame
y GLCanvasFrame
), einfach zu verwendende Methoden zur parallelen Ausführung von Code auf mehreren Kernen ( Parallel
), benutzerfreundliche Geometrie- und Farbkalibrierung von Kameras und Projektoren ( GeometricCalibrator
, ProCamGeometricCalibrator
, ProCamColorCalibrator
), Erkennung und Abgleich von Merkmalspunkten ( ObjectFinder
), eine Reihe von Klassen, die die direkte Bildausrichtung von Projektor-Kamera-Systemen implementieren (hauptsächlich GNImageAligner
, ProjectiveTransformer
, ProjectiveColorTransformer
, ProCamTransformer
y ReflectanceInitializer
), ein Blob-Analysepaket ( Blobs
), sowie verschiedene Funktionen in der JavaCV
Klasse. Einige dieser Klassen haben auch ein OpenCL- und OpenGL-Gegenstück, ihre Namen enden mit CL
oder beginnend mit GL
d.h.: JavaCVCL
, GLCanvasFrame
etc.
Aber wie können wir diese Lösung nutzen?
Hier haben wir eine grundlegende Implementierung des Streamings über 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);
Dieser Teil des Codes zeigt, wie man das FFmpegFrameRecorder-Objekt namens recorder initialisiert. Dieses Objekt wird die von der Kamera erhaltenen Bilder und die vom Mikrofon erhaltenen Samples erfassen und kodieren.
Wenn Sie eine Vorschau in der gleichen Android-App erfassen möchten, müssen wir eine CameraPreview-Klasse implementieren. Diese Klasse konvertiert die von der Kamera gelieferten Rohdaten und erstellt die Vorschau und den Rahmen für den FFmpegFrameRecorder.
Denken Sie daran, ip_destination durch die IP des PCs oder Geräts zu ersetzen, an das Sie den Stream senden möchten. Der Port kann zum Beispiel 8080 sein.
@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;
}
Diese Methode zeigt die Implementierung der onCameraFrame
Methode, die das Mat (Bild) von der Kamera erhält und es als Frame konvertiert und durch das FFmpegFrameRecorder-Objekt aufgezeichnet wird.
@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();
}
}
Das Gleiche gilt für den Ton der audioData
ist eine ShortBuffer
Objekt, das vom FFmpegFrameRecorder aufgezeichnet werden soll.
Auf dem Ziel-PC oder -Gerät können Sie den folgenden Befehl ausführen, um den Stream abzurufen.
ffplay udp://ip_source:port
El ip_source
ist die IP des Smartphones, das den Kamera- und Mikrofon-Stream überträgt. Der Port muss derselbe sein: 8080.
Ich habe eine Lösung in meinem Github-Repository hier erstellt: UDPAVStreamer .
Viel Glück!