VideoLive

Project Url: wbaizx/VideoLive
Introduction: android 视频直播库,视频 H264,H265 硬编码,音频 AAC 编码,使用 UDP 协议提供实时预览,传输,解码播放,录制功能。也支持单独语音对讲
More: Author   ReportBugs   
Tags:

视频直播库,视频 H264,H265 硬编码,音频 AAC 编码,使用 UDP 协议提供实时预览,传输和解码播放以及本地录制。 也提供单独语音对讲功能。

Add it in your root build.gradle at the end of repositories:

Step 1:

  allprojects {
      repositories {
          ...
          maven { url 'https://jitpack.io' }
      }
  }

Step 2:

dependencies {
        compile 'com.github.wbaizx:VideoLive:3.1.1'
}


视频直播和语音都是采用 UDP 协议发送,自行设置 url 和 port。(需要 5.0 以上,仅支持硬编码,分包和命名不规范的地方望谅解 0.0)



相关权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />

视频使用示例:

推流端:

<com.library.live.view.PublishView
    android:id="@+id/publishView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"></com.library.live.view.PublishView>


    publish = new Publish.Buider(this, (PublishView) findViewById(R.id.publishView))
            .setPushMode(new UdpSend("192.168.2.106", 8765))
            .setFrameRate(15)//帧率
            .setVideoCode(VDEncoder.H264)//编码方式
            .setIsPreview(true)//是否需要显示预览(如需后台推流最好设置 false,如果设置 false 则构建 Buider 可以调用单参数方法 Publish.Buider(context))
            .setPublishBitrate(600 * 1024)//推流采样率
            .setCollectionBitrate(600 * 1024)//采集采样率
            .setCollectionBitrateVC(64 * 1024)//音频采集采样率
            .setPublishBitrateVC(24 * 1024)//音频推流采样率
            .setPublishSize(480, 320)//推流分辨率,不要高于预览分辨率
            .setPreviewSize(480, 320)//预览分辨率,决定截屏、录制文件的分辨率
            .setRotate(true)//是否为前置摄像头,默认后置
            .setScreenshotsMode(Publish.CONVERSION)//截屏模式
            .setVideoDirPath(Environment.getExternalStorageDirectory().getPath() + File.separator + "VideoLive")//录制路径,当前为默认路径
            .setPictureDirPath(Environment.getExternalStorageDirectory().getPath() + File.separator + "VideoPicture")//拍照路径,当前为默认路径
            .build();

如果 socket 已经创建需要使用已经有的 socket

   .setPushMode(new UdpSend(socket, "192.168.2.106", 8765))

如果需要按比例显示图像

            .setCenterScaleType(true)

如果需要添加自己的协议

            .setUdpControl(new UdpControlInterface() {
                @Override
                public byte[] Control(byte[] bytes, int offset, int length) {//bytes 为 udp 包数据,offset 为起始位,length 为长度
                    //返回自定义后 udp 包数据,不要做耗时操作。如果调用了此方法不要将原数组返回
                    return new byte[0];
                }
            })

然后在需要推流的地方调用

 publish.start();

停止推流

 publish.stop();

推流过程中可调用以下方法

    publish.rotate();//旋转相机

    publish.startRecode();//开始录制

    publish.stopRecode();//停止录制

    publish.takePicture();//截屏

录制回调通过如下方式实现

    publish.setWriteFileCallback(new WriteFileCallback() {
        @Override
        public void success(String path) {
        }

        @Override
        public void failure(String err) {
        }
    });

截屏回调通过如下方式实现

    publish.setPictureCallback(new PictureCallback() {
        @Override
        public void Success(String path) {
            //截屏回调,path 为图片路径
        }
    });

最后销毁资源

publish.destroy();

接收端:

<com.library.live.view.PlayerView
    android:id="@+id/playerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" />

需要让服务器知道自己是接收方并且知道自己的 IP,自行完成

    player = new Player.Buider((PlayerView) findViewById(R.id.playerView))
            .setPullMode(new UdpRecive(8765))
            .setVideoCode(VDDecoder.H264)//设置解码方式
            .setMultiple(1)//音频调节,倍数限制为 1-8 倍。1 为原声,放大后可能导致爆音。
            .build();

如果程序中其他位置已经使用了相同端口的 socket,需要使用 UdpRecive 的无参构造并手动调用 player.write 喂数据给解码器

    player.write(byte[]);

如果想要控制缓存策略可以在构建时设置如下参数

            .setUdpPacketCacheMin(3)//udp 包缓存数量,以音频为基准
            .setVideoFrameCacheMin(6)//视频帧达到播放条件的缓存帧数

如果需要按比例显示图像

            .setCenterScaleType(true)

可以关闭默认缓冲动画

            .setBufferAnimator(false)//默认开启

如果觉得动画太丑也可以自己根据状态去做个 dialog,通过如下设置回调缓冲状态

            .setIsOutBuffer(new IsOutBuffer() {
                @Override
                public void isBuffer(boolean isBuffer) {
                    /*
                    isBuffer 为 true 开始缓冲,为 false 表示结束缓冲。
                    另外更新 ui 注意,此处回调在线程中。
                     */
                }
            })

如果需要去掉自己添加的协议

            .setUdpControl(new UdpControlInterface() {
                @Override
                public byte[] Control(byte[] bytes, int offset, int length) {//bytes 为接收到的原始数据
                    return new byte[0];//在这里将发送时的自定义处理去掉后返回
                }
            })

动态调节音量

    player.setVoiceIncreaseMultiple();//动态调整音量(放大 pcm 音量,与设备音量无关)

调用播放

     player.start();

停止播放

     player.stop();

销毁资源

     player.destroy();

单独语音对讲使用示例:

发送端:

    speak = new Speak.Buider()
            .setPushMode(new SpeakSend("192.168.2.106", 8765))
            .setPublishBitrate(24 * 1024)//音频推流采样率
            .setVoiceDirPath(Environment.getExternalStorageDirectory().getPath() + File.separator + "VideoTalk")//录制路径,当前为默认路径
            .build();

如果 socket 已经创建需要使用已经有的 socket

            .setPushMode(new SpeakSend(socket, "192.168.2.106",8765))

如果需要添加自己的协议同视频推流一样

            .setUdpControl(new UdpControlInterface() {
                @Override
                public byte[] Control(byte[] bytes, int offset, int length) {
                    return Arrays.copyOf(bytes, length);
                }
            })

然后在需要推流的地方调用(不需要发送语音的时候最好关闭)

    speak.start();

停止推流

    speak.stop();

关于录制应当与推流同步启动同步关闭

    speak.startRecode();//开始录制

    speak.stopRecode();//停止录制

录制回调通过如下方式实现

    speak.setWriteFileCallback(new WriteFileCallback() {
        @Override
        public void success(String name) {
        }

        @Override
        public void failure(String err) {
        }
    });

注意如果同时视频推流和语音推流会出现冲突,如果正在视频推流,则不应该启动语音推流,如果已经启动,需调用 stop 方法关闭。 然后此时启动发送和关闭发送对应如下方法,此时无法录制

    speak.startJustSend();
    speak.stopJustSend();

然后从视频的 setUdpControl 回调中通过音频 tag 取出语音数据,调用如下方法添加到发送队列

    speak.addbytes(byte[]);

获取音量分贝大小(0-90)

    speak.getDecibel();

最后销毁资源

    speak.destroy();

接收端:

    listen = new Listen.Buider()
            .setPullMode(new ListenRecive(8765))
            .setMultiple(1)//音频调节,倍数限制为 1-8 倍。1 为原声,放大后可能导致爆音。
            .build();

同视频推流一样如果需要需要自行传入数据,则调用 ListenRecive 的无参构造,然后调用 write 传入数据

    listenRecive.write();

还可以传入一个接收 socket

    new ListenRecive(socket)

然后控制策略

            .setUdpPacketCacheMin(2)
            .setVoiceFrameCacheMin(5)

包控制方式相同

              .setUdpControl(new UdpControlInterface() {
                  @Override
                  public byte[] Control(byte[] bytes, int offset, int length) {
                      return Arrays.copyOf(bytes, length);
                  }
              })

动态调节音量

    listen.setVoiceIncreaseMultiple(3);//动态调整音量(放大 pcm 音量,与设备音量无关)

启动接收

    listen.start();

停止接收

    listen.stop();

销毁资源

    listen.destroy();

视频和语音推流时如果网络断开不需要做任何处理,网络恢复后会继续推流。 讨厌写文档!

Support Me
Apps
About Me
Google+: Trinea trinea
GitHub: Trinea