FreeSWITCH命令之uuid_broadcast

290 阅读5分钟

介绍

可以让正在进行的通话播放其他的音视频

使用方法

freeswitch@1afb405668f0> uuid_broadcast    
-USAGE: <uuid> <path> [aleg|bleg|holdb|both]

两个分机通话

分机1004呼叫分机1005

freeswitch@a5676290af86> show channels 
uuid,direction,created,created_epoch,name,state,cid_name,cid_num,ip_addr,dest,application,application_data,dialplan,context,read_codec,read_rate,read_bit_rate,write_codec,write_rate,write_bit_rate,video_read_codec,video_write_codec,secure,hostname,presence_id,presence_data,accountcode,callstate,callee_name,callee_num,callee_direction,call_uuid,sent_callee_name,sent_callee_num,initial_cid_name,initial_cid_num,initial_ip_addr,initial_dest,initial_dialplan,initial_context
c2e81b51-c0f7-bef6-31dd-9121c94f2e2c,inbound,2024-10-16 14:54:41,1729061681,verto.rtc/1005,CS_EXECUTE,1004,1004,192.168.3.159,1005,bridge,{origination_callee_id_name=1005,leg_timeout=50}user/1005,XML,context-1,opus,48000,0,opus,48000,0,VP8,VP8,srtp:dtls:AES_CM_128_HMAC_SHA1_80,a5676290af86,1004@xswitch.cn,,1004,ACTIVE,Outbound Call,1005,,c2e81b51-c0f7-bef6-31dd-9121c94f2e2c,,,1004,1004,192.168.3.159,1005,XML,context-1
0192941b-7ad8-7142-a0d0-393781f81c04,outbound,2024-10-16 14:54:41,1729061681,verto.rtc/d91611c1-bffb-10e9-932d-67077c383160,CS_EXCHANGE_MEDIA,1004,1004,192.168.3.159,u:d91611c1-bffb-10e9-932d-67077c383160,,,XML,context-1,opus,48000,0,opus,48000,0,VP8,VP8,srtp:dtls:AES_CM_128_HMAC_SHA1_80,a5676290af86,1005@xswitch.cn,,,ACTIVE,1005,1005,,c2e81b51-c0f7-bef6-31dd-9121c94f2e2c,,,1004,1004,192.168.3.159,u:d91611c1-bffb-10e9-932d-67077c383160,XML,context-1

2 total.

执行uuid_broadcast执行音乐

执行的命令为uuid_broadcast c2e81b51-c0f7-bef6-31dd-9121c94f2e2c playback::local_stream://default, 默认aleg和bleg都会播放音乐,此时双方说话声音听不到了

freeswitch@a5676290af86> uuid_broadcast c2e81b51-c0f7-bef6-31dd-9121c94f2e2c playback::local_stream://default
+OK Message sent

2024-10-16 14:57:01.190819 98.77% [DEBUG] switch_core_media.c:13662 verto.rtc/d91611c1-bffb-10e9-932d-67077c383160 RESUME Jitterbuffer
2024-10-16 14:57:01.290818 98.77% [DEBUG] switch_ivr.c:633 verto.rtc/d91611c1-bffb-10e9-932d-67077c383160 Command Execute [depth=0] playback(local_stream://default)
EXECUTE [depth=0] verto.rtc/d91611c1-bffb-10e9-932d-67077c383160 playback(local_stream://default)
2024-10-16 14:57:01.291819 98.77% [DEBUG] mod_local_stream.c:912 Opening Stream [default] 8000hz
2024-10-16 14:57:01.291819 98.77% [DEBUG] switch_core_file.c:456 File default sample rate 8000 doesn't match requested rate 48000
2024-10-16 14:57:01.291819 98.77% [DEBUG] switch_ivr_play_say.c:1561 Codec Activated L16@48000hz 1 channels 20ms
2024-10-16 14:57:01.291819 98.77% [DEBUG] switch_ivr.c:633 verto.rtc/1005 Command Execute [depth=0] playback(local_stream://default)
EXECUTE [depth=0] verto.rtc/1005 playback(local_stream://default)
2024-10-16 14:57:01.292819 98.77% [DEBUG] mod_local_stream.c:912 Opening Stream [default] 8000hz
2024-10-16 14:57:01.292819 98.77% [DEBUG] switch_core_file.c:456 File default sample rate 8000 doesn't match requested rate 48000
2024-10-16 14:57:01.292819 98.77% [DEBUG] switch_ivr_play_say.c:1561 Codec Activated L16@48000hz 1 channels 20ms

执行uuid_break停止播放音乐,恢复通话

执行的命令为uuid_break c2e81b51-c0f7-bef6-31dd-9121c94f2e2c

freeswitch@a5676290af86> uuid_break c2e81b51-c0f7-bef6-31dd-9121c94f2e2c
+OK

2024-10-16 14:59:55.202818 97.77% [DEBUG] switch_ivr_play_say.c:2012 done playing file local_stream://default
2024-10-16 14:59:55.211817 97.77% [DEBUG] switch_ivr_play_say.c:2012 done playing file local_stream://default

具体实现代码,参见switch_ivr_async.c里的switch_ivr_broadcast函数。

SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const char *path, switch_media_flag_t flags)
{
	switch_channel_t *channel;
	switch_core_session_t *session;
	switch_event_t *event;
	switch_core_session_t *other_session = NULL;
	const char *other_uuid = NULL;
	char *app = "playback";
	char *cause = NULL;
	char *mypath;
	char *p;
	int app_flags = 0, nomedia = 0;

	switch_assert(path);

	if (!(session = switch_core_session_locate(uuid))) {
		return SWITCH_STATUS_FALSE;
	}

	channel = switch_core_session_get_channel(session);

	mypath = strdup(path);
	switch_assert(mypath);

	if ((p = strchr(mypath, ':')) && *(p + 1) == ':') {
		app = mypath;
		*p++ = '\0';
		*p++ = '\0';
		path = p;
	}

	if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
		nomedia = 1;
		switch_ivr_media(uuid, SMF_REBRIDGE);
	}

	if ((cause = strchr(app, '!'))) {
		*cause++ = '\0';
		if (!*cause) {
			cause = "normal_clearing";
		}
	}

	if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_partner_uuid(channel))
		&& (other_session = switch_core_session_locate(other_uuid))) {
		if ((flags & SMF_EXEC_INLINE)) {
			switch_core_session_execute_application_get_flags(other_session, app, path, &app_flags);
			nomedia = 0;
		} else {
			switch_core_session_get_app_flags(app, &app_flags);
			if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");

				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);

				if ((flags & SMF_LOOP)) {
					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
				}

				if ((flags & SMF_HOLD_BLEG)) {
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
				}

				switch_core_session_queue_private_event(other_session, &event, (flags & SMF_PRIORITY));
			}
		}

		switch_core_session_rwunlock(other_session);
		other_session = NULL;
	}

	if ((app_flags & SAF_MEDIA_TAP)) {
		nomedia = 0;
	}

	if ((flags & SMF_ECHO_ALEG)) {
		if ((flags & SMF_EXEC_INLINE)) {
			switch_core_session_execute_application(session, app, path);
		} else {
			if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);

				if ((flags & SMF_LOOP)) {
					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
				}
				if ((flags & SMF_HOLD_BLEG)) {
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
				}

				switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));

				if (nomedia)
					switch_channel_set_flag(channel, CF_BROADCAST_DROP_MEDIA);
			}
		}
	}

	if (cause) {
		if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup");
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", cause);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
			switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));
		}
	}

	switch_core_session_rwunlock(session);
	switch_safe_free(mypath);

	return SWITCH_STATUS_SUCCESS;
}

参考文章