wvp-gb28181-pro集成语音广播功能

由于开发摄像头项目用到了wvp这个框架,但是目前还未集成语音广播功能,所以我就自己写死了一个,不影响视频的预览和上下左右移动,其他影响未知,说步骤

参考了这位大佬的博客https://blog.csdn.net/qq_38795209/article/details/110953058?utm_medium=distribute.pc_relevant_bbs_down.none-task--2~all~first_rank_v2~rank_v29-12.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task--2~all~first_rank_v2~rank_v29-12.nonecase

分为2个部分,第一部分贴代码,第二部分就是说明原理

/**
	 * 打开音频通道
	 *
	 * @param device 视频设备
	 */
	@Override
	public boolean openCameraVoice(Device device,String channelId) {
		try {
			StringBuffer catalogXml = new StringBuffer(400);
			catalogXml.append("<?xml version=\"1.0\"?>\r\n");
			catalogXml.append("<Notify>\r\n");
			catalogXml.append("<CmdType>Broadcast</CmdType>\r\n");
			catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
			catalogXml.append("<SourceID>" + device.getDeviceId() + "</SourceID>\r\n");
			catalogXml.append("<TargetID>" + channelId + "</TargetID>\r\n");
			catalogXml.append("</Notify>\r\n");
			Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", null);
			transmitRequest(device, request, null);
		} catch (SipException | ParseException | InvalidArgumentException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

 

 

/***
	 * 回复200 OK
	 * @param evt
	 * @throws SipException
	 * @throws InvalidArgumentException
	 * @throws ParseException
	 */
	private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
		Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
		String content0=evt.getRequest().toString().replaceAll("(\r\n|\n)","<br/>");
		String content1[]=content0.split("<br/>");
		HashMap<String,String> mapContent=new HashMap<>();
		String channeld="";
		for(int i=0;i<content1.length;i++){
			if(content1[i].length()>2){
				if("=".equals(content1[i].substring(1,2))){
					String content2[]=content1[i].split("=");
					mapContent.put(content2[0],content2[1]);
				}else{
					if(content1[i].startsWith("From")){
						String content2[]=content1[i].split(":");
						mapContent.put("From",content2[2]);
					}else if(content1[i].startsWith("To")){
						String content2[]=content1[i].split(":");
						mapContent.put("To",content2[2]);
					}else if(content1[i].startsWith("Subject")){
						channeld=content1[i].split(",")[1].split(":")[0];
					}
				}
			}else{
				continue;
			}
		}
		String to[]=mapContent.get("To").split("@");
		String from[]=mapContent.get("From").split("@");
		String deviceId=from[0];

		//保存port到redis

		String m=mapContent.get("m").substring(6,11).replaceAll(" ","");
		portAudio=m;
		String portAudio0=m;
		// 添加Contact头
		Address concatAddress = SipFactory.getInstance().createAddressFactory().
				createAddress(SipFactory.getInstance().createAddressFactory().
						createSipURI(to[0], to[1]+":"+"5060"));
		response.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
		response.addHeader(evt.getRequest().getHeader(ContentType.NAME));

		//response.addHeader(evt.getRequest().getHeader(UserAgent.NAME));
		ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("application", "SDP");
		Random random = new Random();
		int random0=(int)Math.floor((random.nextDouble()*10000.0))+10000;
		String portWvp=String.valueOf(random0);
		StringBuffer contentEnd=new StringBuffer("v=0\r\n")
				.append("o="+to[0]+" 0 0 IN IP4 "+to[1]+"\r\n")
				.append("s=Play\r\n")
				.append("c=IN IP4 "+to[1]+"\r\n")
				.append("t=0 0\r\n")
				.append("m=audio "+portWvp+" RTP/AVP 8\r\n")
				.append("a=rtpmap:8 PCMA/"+portWvp+"\r\n")
				.append("a=sendonly\r\n")
				.append("y="+mapContent.get("y")+"\r\n")
				.append("f="+mapContent.get("f").replaceAll("0","")+"\r\n");
		logger.info("content返回结果:"+contentEnd);
		IVideoManagerStorager videoManagerStorager=new VideoManagerRedisStoragerImpl();
		logger.info("wvp往jeecgboot项目发送修改端口命令deviceId="+deviceId+",channeld="+channeld+",portAudio0="+portAudio0);
		videoManagerStorager.updateAudioPort(deviceId,channeld,portAudio0,portWvp);
		response.setContent(contentEnd,contentTypeHeader);
		getServerTransaction(evt).sendResponse(response);
	}

前端收到的mp3文件转g711a文件

/**
     * MP3转换PCMA文件方法
     *
     * @param mp3filePath 原始文件路径
     * @param pcmFilePath 转换文件的保存路径
     */
    public static boolean mp32pcma(String mp3filePath, String pcmFilePath) {
//        String command = "ffmpeg -y -i mp3filePath -acodec pcm_s16le -f s16le -ac 1 -ar 16000 pcmFilePath";
        try {
            String command1 = "ffmpeg  -i ";
            String command2 = " -acodec pcm_alaw -f alaw -ac 1 -ar 8000 ";


            Runtime runtime = Runtime.getRuntime();
            Process exec = runtime.exec(command1 + mp3filePath + command2 + pcmFilePath);
            exec.waitFor();

            exec.destroy();

            return true;
        } catch (Exception e) {
            System.out.println("MP3转换PCM文件 失败");
        }
        return false;
    }

发送rtp文件

public static void sendRtp(int localPort,String cameraIP,int port,String audioFile) throws IOException {
        SendRtp sendRtp=new SendRtp();
        sendRtp.startKillPort(port);
        long ssrc = 255;
        int send_interval_ms = 50;
        int audio_need_len = 400;
        int peerPort = port;
        DatagramSocket ds = null;
        InetAddress peerAddress = null;
        InputStream audio_stream = new FileInputStream(audioFile);
        //ByteArrayInputStream audio_stream = new ByteArrayInputStream(audioFile.getBytes());
        //InputStream audio_stream = new FileInputStream(audioFile);
        try {
            ds = new DatagramSocket(localPort);
        } catch (SocketException e) {
            e.printStackTrace();
            System.exit(1);
        }

        try {
            peerAddress = InetAddress.getByName(cameraIP);
        } catch (UnknownHostException e) {
            e.printStackTrace();
            System.exit(1);
        }

        RtpPacket rtp = new RtpPacket(ssrc);
        byte[] audio_data = new byte[audio_need_len];
        int i=0;
        while (audio_stream.read(audio_data) == audio_need_len) {

            byte[] payload = rtp.packet_g711a(audio_data, audio_data.length);
            DatagramPacket dp = new DatagramPacket(payload, payload.length, peerAddress, peerPort);

            ds.send(dp);
            System.out.println(Arrays.toString(payload));
            System.out.println("发送"+i+"消息-----------------");
            i++;
            try {
                Thread.sleep(send_interval_ms);

            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
        ds.close();
    }

以上的步骤图片

所用工具

有关资料下载

wvp-GB28181集成语音广播demo.rar

https://pan.baidu.com/s/171hz_z8yeyV5miJUpBHNDA     gbk2

wvp集成语音广播信令记录Report.pdf

https://pan.baidu.com/s/1gttyaF8xTwnnY9YT7vx-ZA         gbk2

GB28181-2016 IPC模拟设备 自动化测试工具.rar

https://pan.baidu.com/s/1mPno_P4gp4Ycfc0gThI0Kg     gbk2

WVP-GB28181-Pro是一种视频监控解决方案,旨在支持GB28181协议的环境下部署。该解决方案主要用于构建视频监控系统,以监测和管理安全环境。 WVP-GB28181-Pro的Windows部署可以按照以下步骤进行: 1. 选择适当的硬件设备:首先,您需要选择适合部署WVP-GB28181-Pro的硬件设备。这包括选择一台性能良好的Windows服务器或PC,以及摄像头、监视器等视频监控设备。 2. 安装操作系统:在选择的硬件设备上安装Windows操作系统。推荐使用Windows Server操作系统,因为它更适合部署和管理视频监控系统。 3. 下载和安装WVP-GB28181-Pro软件:从官方网站下载WVP-GB28181-Pro的Windows版本软件。将其安装到您选择的Windows服务器或PC上。 4. 配置参数:在安装完成后,您需要根据实际需求进行各种配置,包括网络设置、视频存储路径、设备连接等。根据需要配置并添加GB28181兼容设备,如摄像头。 5. 启动和测试:配置完成后,启动WVP-GB28181-Pro服务。使用管理界面进行一些基本设置和监控设备的参数调整。随后,可以通过客户端软件访问和监控视频流,同时进行录像、回放和其他操作。 需要注意的是,Windows部署仅提供了一个部署和管理视频监控系统的环境,具体的配置和操作需要根据实际需求和环境来确定。此外,在部署前还需要评估和确保硬件设备的兼容性以及网络的稳定性和带宽要求。 通过以上步骤,您可以在Windows环境下成功部署WVP-GB28181-Pro视频监控系统,并实现对安全环境的有效监控和管理。
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值