使用 VLCJ 下载 RTSP 时跳过帧

Frames getting skipped while download RTSP using VLCJ

我正在尝试从我的 RTSP 流下载视频。大多数时候我都能完美地下载视频。 但在某些情况下,在特定时间范围内,某些帧会被跳过。例如:一个 6 秒的视频,我只得到大约 4 秒。跳过帧时出现以下错误:

MultiFramedRTPSource::doGetNextFrame1(): The total received frame size exceeds the client's buffer size (250000).  17058 bytes of trailing data will be dropped!

有什么解决办法吗?

完整的 VLC 输出:

00000000212b5bc0] x264 encoder: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2

[00000000212b5bc0] x264 encoder: profile High, level 5.0

[0000000021303460] avcodec generic: Using D3D11VA (Intel(R) HD Graphics 630, vendor 8086(Intel), device 5912, revision 4) for hardware decoding
[00000000212b5bc0] x264 encoder: using SAR=1/1

[00000000212b5bc0] x264 encoder: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2

[00000000212b5bc0] x264 encoder: profile High, level 5.0

MultiFramedRTPSource::doGetNextFrame1(): The total received frame size exceeds the client's buffer size (250000).  17058 bytes of trailing data will be dropped!
[00000000212b5bc0] x264 encoder: frame I:1     Avg QP:17.27  size:265736

[00000000212b5bc0] x264 encoder: frame P:30    Avg QP:18.12  size: 29747

[00000000212b5bc0] x264 encoder: frame B:89    Avg QP:22.63  size:  3406

[00000000212b5bc0] x264 encoder: consecutive B-frames:  0.8%  0.0%  2.5% 96.7%

[00000000212b5bc0] x264 encoder: mb I  I16..4: 40.8% 14.5% 44.7%

[00000000212b5bc0] x264 encoder: mb P  I16..4:  1.1%  0.5%  0.4%  P16..4: 36.4%  3.7%  3.7%  0.0%  0.0%    skip:54.3%

[00000000212b5bc0] x264 encoder: mb B  I16..4:  0.0%  0.0%  0.0%  B16..8: 12.9%  0.0%  0.0%  direct: 8.0%  skip:79.1%  L0:38.9% L1:59.0% BI: 2.0%

[00000000212b5bc0] x264 encoder: 8x8 transform intra:18.3% inter:40.4%

[00000000212b5bc0] x264 encoder: coded y,uvDC,uvAC intra: 65.4% 50.5% 10.4% inter: 2.9% 12.8% 0.1%

[00000000212b5bc0] x264 encoder: i16 v,h,dc,p: 34% 23% 28% 15%

[00000000212b5bc0] x264 encoder: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 20% 41%  2%  2%  3%  3%  2%  4%

[00000000212b5bc0] x264 encoder: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 31% 29% 18%  3%  3%  4%  4%  3%  5%

[00000000212b5bc0] x264 encoder: i8c dc,h,v,p: 52% 25% 20%  2%

[00000000212b5bc0] x264 encoder: Weighted P-Frames: Y:0.0% UV:0.0%

[00000000212b5bc0] x264 encoder: ref P L0: 65.3%  3.1% 21.4% 10.2%

[00000000212b5bc0] x264 encoder: ref B L0: 87.7% 11.2%  1.0%

[00000000212b5bc0] x264 encoder: ref B L1: 92.7%  7.3%

[00000000212b5bc0] x264 encoder: kb/s:2922.60

从 RTSP 下载视频的代码:

String mrl = "rtsp://<URL>";
String videoName = "E:\cam11558337161068.mp4";
String options = ":sout=#transcode{vcodec=mp4v,venc=x264{cfr=16},scale=1,acodec=mp4a,ab=160,channels=2,samplerate=44100}:file{dst=" + videoName + "}";

final CountDownLatch sync = new CountDownLatch(1);
MediaPlayerFactory factory = new MediaPlayerFactory();
final MediaPlayer mediaPlayer = factory.mediaPlayers().newMediaPlayer();

mediaPlayer.events().addMediaPlayerEventListener(new MediaPlayerEventAdapter() {
    @Override
    public void error(MediaPlayer mediaPlayer) {
        sync.countDown();
    }

    @Override
    public void finished(MediaPlayer mediaPlayer) {
        mediaPlayer.release();
        factory.release();
        try {
            Thread.sleep(1000);
        }
        catch(InterruptedException e) {
        }                
    }

    @Override
    public void buffering(MediaPlayer mediaPlayer, float newCache) {
        System.out.println("Buffering ...");
    }

    @Override
    public void playing(MediaPlayer mediaPlayer) {
        System.out.println("Playing ...");
    }

});

mediaPlayer.media().prepare(mrl, options);
mediaPlayer.controls().start();

try {
    sync.await();
}
catch (InterruptedException e) {
    e.printStackTrace();
}

System.out.println("Done");

假设原因与您收到的丢弃消息有关:The total received frame size exceeds the client's buffer size (250000),您可能需要更改 RTSP 帧缓冲区的大小。这是通过传递以下选项来完成的:

"--rtsp-frame-buffer-size=500000"

当然你把大小设置成你认为合适的。我没有使用带有 Java 绑定的 libVLC 的经验,但我相信您可以在实例化 MediaPlayerFactory 时传入构造函数选项。这是来自一些绑定代码:

public  MediaPlayerFactory(String... libvlcArgs) {
    this(LibVlcFactory.factory().atLeast("2.1.0").create(), libvlcArgs);
}

...所以我相信这是您以这种方式传递参数的地方:

String[] args = {
  "--rtsp-frame-buffer-size", 
  "500000",
};

mediaPlayerFactory = new MediaPlayerFactory(args);

还有许多其他选项可供您传入。