UE4借助Cross-Platform Voice Chat Pro插件实现iOS上录音

Cross-Platform Voice Chat Pro插件

Universal cross-platform Pro Voice Chat是一个在Unreal Engine上多平台多人对战混合平台战队语音通讯的工具插件,支持 Windows / Android / iOS平台(不支持Mac电脑)。

录音功能

要实现录音功能,就要能访问Microphone采集的音频采样数据,Cross-Platform Voice Chat Pro插件的MicrophoneSpeakComponent组件有两个蓝图回调函数,可以帮我们获得实时采集音频数据。

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UNIVERSALVOICECHATPRO_API UMicrophoneSpeakComponent : public UActorComponent
{
    
    
	GENERATED_BODY()
		// 可以帮我们获得Samples Data(音频采集数据)
		DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDataMicrophoneReceived, const TArray<uint8>&, data);
		// 可以帮我们获得实时采集音频的Volume值(实现示波器)
		DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDataMicrophoneCurrentVolume, float, currentVolume);
public:
	UMicrophoneSpeakComponent();
	//...
}

借助插件实现录音

Cross-Platform Voice Chat Pro插件是作为团队语音功能实现的,需要用到多人游戏框架,PC上测试需要打开多人子系统和Voice功能。
编辑Config/DefaultEngine.ini,增加以下文本
[OnlineSubsystem]
DefaultPlatformService=Null
bHasVoiceEnabled=true

[Voice]
bEnabled=true

按照文档,在服务器中创建PlayerVoiceChatActor,然后通过多人游戏框架的Replication功能复制到客户端。
在这里插入图片描述
如果只使用iOS的录制功能,就不需要考虑整个插件框架了,单独使用MicrophoneSpeak组件即可。
给自己的游戏角色增加MicrophoneSpeak组件
在这里插入图片描述
在BeginPlay增加绑定回调事件
获取实时Volume值
在这里插入图片描述

获取Samples Data
在这里插入图片描述

启动录制
在这里插入图片描述

移动端权限

移动端启动录音前要调用VoiceChatAskMicrophonePermission请求语音权限,这是一段混合代码

void  UUniversalVoiceChat::VoiceChatAskMicrophonePermission() {
    
    
#if PLATFORM_IOS
	[[AVAudioSession sharedInstance] requestRecordPermission:^ (BOOL granted) {
    
    
			if (granted)
			{
    
    
			}
			else
			{
    
    
			}
	}];
#endif
#if PLATFORM_ANDROID
	UAudioCaptureAndroid::AndroidAskPermission();
#endif
#if PLATFORM_WINDOWS	
#endif
}

注意,在调用这段代码以前要先配置plist,增加麦克风录音权限,否则调用VoiceChatAskMicrophonePermission时App会直接崩溃而没有任何提示。
Unreal Engine编译iOS可以在Project Setting中增加plist配置
Peoject Setting->iOS->Extra PList Data->Additional Plist Data
增加录音权限

<key>NSMicrophoneUsageDescription</key><string>Microphone is used for AR functionality</string>

在这里插入图片描述

在Windows平台上测试

在Windows平台上测试时,以上方法不能获取到数据,原因是插件在Windows平台上判断了是服务端还是客户端,执行响应代码时默认了MicrophoneSpeak组件在PlayerVoiceChatActor中使用,需要我们作一些修改。

	// only capture if this component is from local voice chat actor
	if (GetNetMode() != NM_DedicatedServer && UUniversalVoiceChat::GetMyPlayerVoiceActor() != NULL && UUniversalVoiceChat::GetMyPlayerVoiceActor() == (AActor*)GetOwner()){
    
    
	
#if PLATFORM_WINDOWS
		if (PCVoiceCapture.IsValid() && PCVoiceCapture->IsCapturing()) {
    
    
			uint32 VoiceCaptureBytesAvailable = 0;
			EVoiceCaptureState::Type CaptureState = PCVoiceCapture->GetCaptureState(VoiceCaptureBytesAvailable);
			
			PCVoiceCaptureBuffer.Reset();

			if (CaptureState == EVoiceCaptureState::Ok && VoiceCaptureBytesAvailable > 0)
			{
    
    
				float VoiceCaptureTotalSquared = 0;

				PCVoiceCaptureBuffer.SetNumUninitialized(VoiceCaptureBytesAvailable);
				
				// get current voice data
				uint64 OutSampleCounter = 0;
				uint32 OutAvailableVoiceData = 0;
				PCVoiceCapture->GetVoiceData(PCVoiceCaptureBuffer.GetData(), VoiceCaptureBytesAvailable, OutAvailableVoiceData, OutSampleCounter);
				UE_LOG(LogTemp, Warning, TEXT("OutAvailableVoiceData %d OutSampleCounter %d"), OutAvailableVoiceData, OutSampleCounter);

				OnDataMicrophoneReceived.Broadcast(PCVoiceCaptureBuffer);

				PCVoiceCaptureBufferAppended.Append(PCVoiceCaptureBuffer);			
					
				int32 amountWillBeRemind = PCVoiceCaptureBufferAppended.Num() % encoderBytesPerFrame;
				int32 frameSentToOpus = PCVoiceCaptureBufferAppended.Num() / encoderBytesPerFrame;
				int32 startOffsetRemind = (PCVoiceCaptureBufferAppended.Num() / encoderBytesPerFrame) * encoderBytesPerFrame - 1;
					

				//UE_LOG(LogTemp, Warning, TEXT("PCVoiceCaptureBuffer %d PCVoiceCaptureBufferAppended %d frameSentToOpus %d encoderBytesPerFrame %d"), 
				//	PCVoiceCaptureBuffer.Num(), PCVoiceCaptureBufferAppended.Num(), frameSentToOpus, encoderBytesPerFrame);

				// transmit local voice data to server	
				if (frameSentToOpus > 0) {
    
    
					int32 uint8sizeBufferPCMMic = frameSentToOpus * encoderBytesPerFrame;//PCVoiceCaptureBuffer.Num();
					uint8 *pointerBufferPCMMic = (uint8*)malloc(sizeof(uint8) * uint8sizeBufferPCMMic);

					//UE_LOG(LogTemp, Warning, TEXT("prepare transmitDataToOtherAndLocal %d %d"), uint8sizeBufferPCMMic, PCVoiceCaptureBuffer.Num());

					memcpy(pointerBufferPCMMic, PCVoiceCaptureBufferAppended.GetData(), uint8sizeBufferPCMMic);					
					transmitDataToOtherAndLocal(pointerBufferPCMMic, uint8sizeBufferPCMMic);

					// remove transmited data
					PCVoiceCaptureBufferAppended.RemoveAt(0, uint8sizeBufferPCMMic, false);
				}
			}
		}
#endif
	}

我们可以把这个判断去掉。

if (true || (GetNetMode() != NM_DedicatedServer && UUniversalVoiceChat::GetMyPlayerVoiceActor() != NULL && UUniversalVoiceChat::GetMyPlayerVoiceActor() == (AActor*)GetOwner()))

这样就可以在编辑器中调试获取音频了
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_31042143/article/details/129479405