by Anonymous » 14 Sep 2025, 23:20
Ich versuche, eine Videodatei und eine Audiodatei in einen einzigen MP4 mit FFMPEG -Bibliotheken (libavformat, libavcodec, libavutil usw.) über JNI on Android zu verschmelzen. Hier ist der vereinfachte Ansatz, den ich verwende: < /p>
Code: Select all
const char *videoPath = (*env)->GetStringUTFChars(env, jVideoPath, 0);
const char *audioPath = (*env)->GetStringUTFChars(env, jAudioPath, 0);
const char *outPath = (*env)->GetStringUTFChars(env, jOutPath, 0);
avformat_network_init();
AVFormatContext *videoFmtCtx = NULL;
AVFormatContext *audioFmtCtx = NULL;
AVFormatContext *outFmtCtx = NULL;
LOGD("Opening video file: %s", videoPath);
LOGD("Opening audio file: %s", audioPath);
LOGD("Output path: %s", outPath);
if (avformat_open_input(&videoFmtCtx, videoPath, NULL, NULL) < 0) return -1;
if (avformat_open_input(&audioFmtCtx, audioPath, NULL, NULL) < 0) return -2;
if (avformat_alloc_output_context2(&outFmtCtx, NULL, NULL, outPath) < 0) return -3;
AVStream *inVideo = videoFmtCtx->streams[0];
AVStream *outVideo = avformat_new_stream(outFmtCtx, NULL);
avcodec_parameters_copy(outVideo->codecpar, inVideo->codecpar);
outVideo->time_base = inVideo->time_base;
AVStream *inAudio = audioFmtCtx->streams[0];
AVStream *outAudio = avformat_new_stream(outFmtCtx, NULL);
avcodec_parameters_copy(outAudio->codecpar, inAudio->codecpar);
outAudio->time_base = inAudio->time_base;
if (!(outFmtCtx->oformat->flags & AVFMT_NOFILE)) {
if (avio_open(&outFmtCtx->pb, outPath, AVIO_FLAG_WRITE) < 0) return -4;
}
if (avformat_write_header(outFmtCtx, NULL) < 0) return -5;
AVPacket pkt;
int videoDone = 0, audioDone = 0;
while (!videoDone || !audioDone) {
int videoRead = 0, audioRead = 0;
if (!videoDone && av_read_frame(videoFmtCtx, &pkt) >= 0) {
pkt.stream_index = outVideo->index;
av_packet_rescale_ts(&pkt, inVideo->time_base, outVideo->time_base);
if (av_interleaved_write_frame(outFmtCtx, &pkt) < 0) {
LOGE("Failed to write video packet");
}
av_packet_unref(&pkt);
videoRead = 1;
} else {
videoDone = 1;
}
if (!audioDone && av_read_frame(audioFmtCtx, &pkt) >= 0) {
pkt.stream_index = outAudio->index;
av_packet_rescale_ts(&pkt, inAudio->time_base, outAudio->time_base);
if (av_interleaved_write_frame(outFmtCtx, &pkt) < 0) {
LOGE("Failed to write audio packet");
}
av_packet_unref(&pkt);
audioRead = 1;
} else {
audioDone = 1;
}
// if both streams have no packets left, exit
if (!videoRead && !audioRead) break;
}
av_write_trailer(outFmtCtx);
avformat_close_input(&videoFmtCtx);
avformat_close_input(&audioFmtCtx);
if (!(outFmtCtx->oformat->flags & AVFMT_NOFILE)) avio_closep(&outFmtCtx->pb);
avformat_free_context(outFmtCtx);
(*env)->ReleaseStringUTFChars(env, jVideoPath, videoPath);
(*env)->ReleaseStringUTFChars(env, jAudioPath, audioPath);
(*env)->ReleaseStringUTFChars(env, jOutPath, outPath);
LOGD("mergeAV finished successfully");
return 0;
Problem:
Die fusionierte Datei spielt Audio korrekt ab, aber das Video ist schwarz. Verwenden der Bibliotheken direkt. geladen < /p>
ordnungsgemäß geöffnete Eingangsformate und zugeteilte Ausgangskontext < /p>
Streams mit avcodec_parameters_copy < /p>
kopiert Ich verwende keine FFMPEG-Befehlszeile. Umschlüsse, Stream -Verschachtel usw.) wäre äußerst hilfreich.
Ich versuche, eine Videodatei und eine Audiodatei in einen einzigen MP4 mit FFMPEG -Bibliotheken (libavformat, libavcodec, libavutil usw.) über JNI on Android zu verschmelzen. Hier ist der vereinfachte Ansatz, den ich verwende: < /p>
[code]
const char *videoPath = (*env)->GetStringUTFChars(env, jVideoPath, 0);
const char *audioPath = (*env)->GetStringUTFChars(env, jAudioPath, 0);
const char *outPath = (*env)->GetStringUTFChars(env, jOutPath, 0);
avformat_network_init();
AVFormatContext *videoFmtCtx = NULL;
AVFormatContext *audioFmtCtx = NULL;
AVFormatContext *outFmtCtx = NULL;
LOGD("Opening video file: %s", videoPath);
LOGD("Opening audio file: %s", audioPath);
LOGD("Output path: %s", outPath);
if (avformat_open_input(&videoFmtCtx, videoPath, NULL, NULL) < 0) return -1;
if (avformat_open_input(&audioFmtCtx, audioPath, NULL, NULL) < 0) return -2;
if (avformat_alloc_output_context2(&outFmtCtx, NULL, NULL, outPath) < 0) return -3;
AVStream *inVideo = videoFmtCtx->streams[0];
AVStream *outVideo = avformat_new_stream(outFmtCtx, NULL);
avcodec_parameters_copy(outVideo->codecpar, inVideo->codecpar);
outVideo->time_base = inVideo->time_base;
AVStream *inAudio = audioFmtCtx->streams[0];
AVStream *outAudio = avformat_new_stream(outFmtCtx, NULL);
avcodec_parameters_copy(outAudio->codecpar, inAudio->codecpar);
outAudio->time_base = inAudio->time_base;
if (!(outFmtCtx->oformat->flags & AVFMT_NOFILE)) {
if (avio_open(&outFmtCtx->pb, outPath, AVIO_FLAG_WRITE) < 0) return -4;
}
if (avformat_write_header(outFmtCtx, NULL) < 0) return -5;
AVPacket pkt;
int videoDone = 0, audioDone = 0;
while (!videoDone || !audioDone) {
int videoRead = 0, audioRead = 0;
if (!videoDone && av_read_frame(videoFmtCtx, &pkt) >= 0) {
pkt.stream_index = outVideo->index;
av_packet_rescale_ts(&pkt, inVideo->time_base, outVideo->time_base);
if (av_interleaved_write_frame(outFmtCtx, &pkt) < 0) {
LOGE("Failed to write video packet");
}
av_packet_unref(&pkt);
videoRead = 1;
} else {
videoDone = 1;
}
if (!audioDone && av_read_frame(audioFmtCtx, &pkt) >= 0) {
pkt.stream_index = outAudio->index;
av_packet_rescale_ts(&pkt, inAudio->time_base, outAudio->time_base);
if (av_interleaved_write_frame(outFmtCtx, &pkt) < 0) {
LOGE("Failed to write audio packet");
}
av_packet_unref(&pkt);
audioRead = 1;
} else {
audioDone = 1;
}
// if both streams have no packets left, exit
if (!videoRead && !audioRead) break;
}
av_write_trailer(outFmtCtx);
avformat_close_input(&videoFmtCtx);
avformat_close_input(&audioFmtCtx);
if (!(outFmtCtx->oformat->flags & AVFMT_NOFILE)) avio_closep(&outFmtCtx->pb);
avformat_free_context(outFmtCtx);
(*env)->ReleaseStringUTFChars(env, jVideoPath, videoPath);
(*env)->ReleaseStringUTFChars(env, jAudioPath, audioPath);
(*env)->ReleaseStringUTFChars(env, jOutPath, outPath);
LOGD("mergeAV finished successfully");
return 0;
[/code]
Problem:
Die fusionierte Datei spielt Audio korrekt ab, aber das Video ist schwarz. Verwenden der Bibliotheken direkt. geladen < /p>
ordnungsgemäß geöffnete Eingangsformate und zugeteilte Ausgangskontext < /p>
Streams mit avcodec_parameters_copy < /p>
kopiert Ich verwende keine FFMPEG-Befehlszeile. Umschlüsse, Stream -Verschachtel usw.) wäre äußerst hilfreich.