@ -13,6 +13,7 @@ import com.cloud.kicc.common.security.util.SecurityUtils;
@@ -13,6 +13,7 @@ import com.cloud.kicc.common.security.util.SecurityUtils;
import com.cloud.kicc.system.api.entity.ImContent ;
import com.cloud.kicc.system.api.entity.OssFile ;
import com.cloud.kicc.system.api.enums.ImMessageTypeEnum ;
import com.cloud.kicc.system.config.OpenAiConfigProperties ;
import com.cloud.kicc.system.mapper.ImContentMapper ;
import com.cloud.kicc.system.service.FileService ;
import com.cloud.kicc.system.service.IImContentService ;
@ -30,7 +31,8 @@ import com.theokanning.openai.service.OpenAiService;
@@ -30,7 +31,8 @@ import com.theokanning.openai.service.OpenAiService;
import lombok.RequiredArgsConstructor ;
import lombok.SneakyThrows ;
import okhttp3.ResponseBody ;
import org.bytedeco.javacv.FFmpegFrameGrabber ;
import org.jaudiotagger.audio.AudioFile ;
import org.jaudiotagger.audio.AudioFileIO ;
import org.springframework.stereotype.Service ;
import org.springframework.transaction.annotation.Transactional ;
import org.springframework.web.multipart.MultipartFile ;
@ -61,6 +63,8 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
@@ -61,6 +63,8 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
private final OssTemplate ossTemplate ;
private final OpenAiConfigProperties openAiConfigProperties ;
@Override
public IPage < Map < String , Object > > listHistoryMessage ( Page page , ImContent imContent ) {
return baseMapper . listHistoryMessage ( page , imContent ) ;
@ -92,64 +96,74 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
@@ -92,64 +96,74 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
fileService . save ( sendOssOssFile ) ;
imContent . setFiles ( sendOssOssFile . getId ( ) ) ;
File inputVoiceFile = File . createTempFile ( sendFileName , StrUtil . DOT + FileUtil . extName ( file . getOriginalFilename ( ) ) ) ;
File outputVoiceFile = File . createTempFile ( sendFileName , StrUtil . DOT + FileUtil . extName ( file . getOriginalFilename ( ) ) ) ;
ImContent receiveContent ;
OssFile receiveOssOssFile ;
try {
// 语音转文字
File voiceFile = File . createTempFile ( sendFileName , StrUtil . DOT + FileUtil . extName ( file . getOriginalFilename ( ) ) ) ;
CreateTranscriptionRequest request = CreateTranscriptionRequest . builder ( )
. model ( "whisper-1" )
. language ( "zh" )
. build ( ) ;
FileUtil . writeBytes ( file . getBytes ( ) , voiceFile ) ;
TranscriptionResult transcriptionResult = openAiService . createTranscription ( request , voiceFile ) ;
if ( voiceFile . delete ( ) ) {
System . out . println ( "已成功删除临时文件!" ) ;
}
FileUtil . writeBytes ( file . getBytes ( ) , inputVoiceFile ) ;
TranscriptionResult transcriptionResult = openAiService . createTranscription ( request , inputVoiceFile ) ;
imContent . setContent ( transcriptionResult . getText ( ) ) ;
ImContent content = askChatCompletion ( imContent ) ;
content . setContentType ( ImMessageTypeEnum . AUDIO . getValue ( ) ) ;
// ai涡轮增压
receiveContent = askChatCompletion ( imContent ) ;
receiveContent . setContentType ( ImMessageTypeEnum . AUDIO . getValue ( ) ) ;
// 文字转语音
CreateSpeechRequest createSpeechRequest = CreateSpeechRequest . builder ( )
. model ( "tts-1" )
. input ( content . getContent ( ) )
. voice ( "nova" )
. input ( re ceiveC ontent. getContent ( ) )
. voice ( openAiConfigProperties . getVoice ( ) )
. responseFormat ( FileUtil . extName ( speechName ) )
. speed ( 1 . 0 )
. build ( ) ;
ResponseBody responseBody = openAiService . createSpeech ( createSpeechRequest ) ;
FileUtil . writeBytes ( responseBody . bytes ( ) , outputVoiceFile ) ;
// 获取音频时长
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber ( responseBody . byteStream ( ) ) ;
grabber . start ( ) ;
long durationInSec = grabber . getFormatContext ( ) . duration ( ) / 1000000 ;
grabber . close ( ) ;
// 获取输出音频时长
AudioFile outputAudioFile = AudioFileIO . read ( outputVoiceFile ) ;
long outputVoiceDuration = outputAudioFile . getAudioHeader ( ) . getTrackLength ( ) ;
// 构建发送文件信息进行OSS存储
OssFile receiveOssOssFile = new OssFile ( )
receiveOssOssFile = new OssFile ( )
. setFileName ( receiveFileName )
. setBucketName ( ossProperties . getBucketName ( ) )
. setOriginal ( speechName )
. setType ( FileUtil . extName ( speechName ) )
. setFileSize ( responseBody . contentLength ( ) )
. setDuration ( durationInSec )
. setDuration ( outputVoiceDuration )
. setMimeType ( Objects . requireNonNull ( responseBody . contentType ( ) ) . toString ( ) ) ;
ossTemplate . putObject ( ossProperties . getBucketName ( ) , receiveFileName , Objects . requireNonNull ( responseBody . contentType ( ) ) . toString ( ) , responseBody . byteStream ( ) ) ;
ossTemplate . putObject ( ossProperties . getBucketName ( ) , receiveFileName , Objects . requireNonNull ( responseBody . contentType ( ) ) . toString ( ) , FileUtil . getInputStream ( outputVoiceFile ) ) ;
String receiveVoiceUrl = ossTemplate . getObjectURL ( ossProperties . getBucketName ( ) , receiveFileName ) ;
receiveOssOssFile . setAvailablePath ( receiveVoiceUrl ) ;
fileService . save ( receiveOssOssFile ) ;
} catch ( Exception e ) {
throw new CheckedException ( e . getLocalizedMessage ( ) ) ;
} finally {
if ( inputVoiceFile . delete ( ) )
System . out . println ( "已成功删除临时输入语音文件!" ) ;
if ( outputVoiceFile . delete ( ) )
System . out . println ( "已成功删除临时输输出语音文件!" ) ;
}
// 保存AI回复聊天记录
content . setFiles ( receiveOssOssFile . getId ( ) ) ;
super . save ( content ) ;
Map < String , Object > result = Convert . toMap ( String . class , Object . class , content ) ;
// ai chat message build
receiveContent . setFiles ( receiveOssOssFile . getId ( ) ) ;
super . save ( receiveContent ) ;
Map < String , Object > result = Convert . toMap ( String . class , Object . class , receiveContent ) ;
result . putAll ( Convert . toMap ( String . class , Object . class , receiveOssOssFile ) ) ;
return result ;
} else {
// 保存AI回复聊天记录
ImContent content = askChatCompletion ( imContent ) ;
super . save ( content ) ;
return Convert . toMap ( String . class , Object . class , content ) ;
// ai chat message build
ImContent receiveContent = askChatCompletion ( imContent ) ;
super . save ( receiveContent ) ;
return Convert . toMap ( String . class , Object . class , receiveContent ) ;
}
}