Default Changelist
This commit is contained in:
@@ -25,6 +25,26 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.mashape.unirest</groupId>
|
||||
<artifactId>unirest-java</artifactId>
|
||||
<version>1.4.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
<version>4.6.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nls</groupId>
|
||||
<artifactId>nls-sdk-transcriber</artifactId>
|
||||
<version>2.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nls</groupId>
|
||||
<artifactId>nls-sdk-common</artifactId>
|
||||
<version>2.1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-system</artifactId>
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.tikhup;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.service.tikhup.TikHupService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "TikHup - TikTok数据管理", description = "TikHup平台TikTok数据获取相关接口")
|
||||
@RestController
|
||||
@RequestMapping("/ai/tikHup")
|
||||
@RequiredArgsConstructor
|
||||
public class TikHupController {
|
||||
|
||||
private final TikHupService tikHupService;
|
||||
|
||||
@GetMapping("/fetch_user_post_videos")
|
||||
@Operation(
|
||||
summary = "获取用户主页作品数据",
|
||||
description = "通过TikHup API获取指定用户的TikTok作品数据,包括视频列表、用户信息等"
|
||||
)
|
||||
public Object fetch_user_post_videos(
|
||||
@RequestParam String type,
|
||||
@RequestParam String sec_user_id,
|
||||
@RequestParam int max_cursor,
|
||||
@RequestParam int count) {
|
||||
return tikHupService.fetch_user_post_videos(type, sec_user_id,max_cursor, count);
|
||||
}
|
||||
|
||||
@PostMapping("/videoToCharacters")
|
||||
@Operation(summary = "音频转文字", description = "音频转文字接口")
|
||||
public Object videoToCharacters(@RequestBody Map<String,Object> fileLinkMap) {
|
||||
String fileLink = (String) fileLinkMap.get("fileLink");
|
||||
return tikHupService.videoToCharacters(fileLink);
|
||||
}
|
||||
|
||||
@PostMapping("/videoToCharacters2")
|
||||
@Operation(summary = "音频转文字", description = "音频转文字接口")
|
||||
public Object videoToCharacters2(@RequestBody Map<String,Object> fileLinkMap) {
|
||||
List<String> fileLinkList = (List<String>) fileLinkMap.get("fileLinkList");
|
||||
return tikHupService.videoToCharacters2(fileLinkList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "TikToken - TikToken管理 Request VO")
|
||||
@TableName("tik_token")
|
||||
@Data
|
||||
public class TikTokenVO {
|
||||
|
||||
@Schema(
|
||||
description = "TikHup平台API地址",
|
||||
requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "https://api.tikhub.io/api/v1/xiaohongshu/app/get_user_info",
|
||||
title = "平台API地址"
|
||||
)
|
||||
@TableField(value = "platform_url")
|
||||
private String platformUrl;
|
||||
|
||||
@Schema(
|
||||
description = "TikHup平台访问Token,用于API认证",
|
||||
requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "y15aJOgphU+dik4QGaCW3CL2bR7eQ6ZA2Tz3tUe8c6ycoW27OX+zRTO6Ow==",
|
||||
title = "平台访问Token"
|
||||
)
|
||||
@TableField(value = "platform_token")
|
||||
private String platformToken;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.mysql.tikhup;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo.TikTokenVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface TikHupMapper extends BaseMapperX<TikTokenVO> {
|
||||
|
||||
default TikTokenVO getPlatformToken(String platformUrl) {
|
||||
return selectOne("platform_url",platformUrl);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package cn.iocoder.yudao.module.ai.service.tikhup;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyuncs.CommonRequest;
|
||||
import com.aliyuncs.CommonResponse;
|
||||
import com.aliyuncs.DefaultAcsClient;
|
||||
import com.aliyuncs.IAcsClient;
|
||||
import com.aliyuncs.exceptions.ClientException;
|
||||
import com.aliyuncs.http.MethodType;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
|
||||
public class TikFileTransCharacters {
|
||||
|
||||
// 地域ID,常量,固定值。
|
||||
public static final String REGIONID = "cn-shanghai";
|
||||
public static final String ENDPOINTNAME = "cn-shanghai";
|
||||
public static final String PRODUCT = "nls-filetrans";
|
||||
public static final String DOMAIN = "filetrans.cn-shanghai.aliyuncs.com";
|
||||
public static final String API_VERSION = "2018-08-17"; // 中国站版本
|
||||
// public static final String API_VERSION = "2019-08-23"; // 国际站版本
|
||||
public static final String POST_REQUEST_ACTION = "SubmitTask";
|
||||
public static final String GET_REQUEST_ACTION = "GetTaskResult";
|
||||
// 请求参数
|
||||
public static final String KEY_APP_KEY = "appkey";
|
||||
public static final String KEY_FILE_LINK = "file_link";
|
||||
public static final String KEY_VERSION = "version";
|
||||
public static final String KEY_ENABLE_WORDS = "enable_words";
|
||||
// 响应参数
|
||||
public static final String KEY_TASK = "Task";
|
||||
public static final String KEY_TASK_ID = "TaskId";
|
||||
public static final String KEY_STATUS_TEXT = "StatusText";
|
||||
public static final String KEY_RESULT = "Result";
|
||||
// 状态值
|
||||
public static final String STATUS_SUCCESS = "SUCCESS";
|
||||
private static final String STATUS_RUNNING = "RUNNING";
|
||||
private static final String STATUS_QUEUEING = "QUEUEING";
|
||||
// 阿里云鉴权client
|
||||
IAcsClient client;
|
||||
public TikFileTransCharacters(String accessKeyId, String accessKeySecret) {
|
||||
// 设置endpoint
|
||||
try {
|
||||
DefaultProfile.addEndpoint(ENDPOINTNAME, REGIONID, PRODUCT, DOMAIN);
|
||||
} catch (ClientException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 创建DefaultAcsClient实例并初始化
|
||||
DefaultProfile profile = DefaultProfile.getProfile(REGIONID, accessKeyId, accessKeySecret);
|
||||
this.client = new DefaultAcsClient(profile);
|
||||
}
|
||||
public String submitFileTransRequest(String appKey, String fileLink) {
|
||||
/**
|
||||
* 1. 创建CommonRequest,设置请求参数。
|
||||
*/
|
||||
CommonRequest postRequest = new CommonRequest();
|
||||
// 设置域名
|
||||
postRequest.setDomain(DOMAIN);
|
||||
// 设置API的版本号,格式为YYYY-MM-DD。
|
||||
postRequest.setVersion(API_VERSION);
|
||||
// 设置action
|
||||
postRequest.setAction(POST_REQUEST_ACTION);
|
||||
// 设置产品名称
|
||||
postRequest.setProduct(PRODUCT);
|
||||
/**
|
||||
* 2. 设置录音文件识别请求参数,以JSON字符串的格式设置到请求Body中。
|
||||
*/
|
||||
JSONObject taskObject = new JSONObject();
|
||||
// 设置appkey
|
||||
taskObject.put(KEY_APP_KEY, appKey);
|
||||
// 设置音频文件访问链接
|
||||
taskObject.put(KEY_FILE_LINK, fileLink);
|
||||
// 新接入请使用4.0版本,已接入(默认2.0)如需维持现状,请注释掉该参数设置。
|
||||
taskObject.put(KEY_VERSION, "4.0");
|
||||
// 设置是否输出词信息,默认为false,开启时需要设置version为4.0及以上。
|
||||
taskObject.put(KEY_ENABLE_WORDS, true);
|
||||
String task = taskObject.toJSONString();
|
||||
System.out.println(task);
|
||||
// 设置以上JSON字符串为Body参数。
|
||||
postRequest.putBodyParameter(KEY_TASK, task);
|
||||
// 设置为POST方式的请求。
|
||||
postRequest.setMethod(MethodType.POST);
|
||||
// postRequest.setHttpContentType(FormatType.JSON); //当aliyun-java-sdk-core 版本为4.6.0及以上时,请取消该行注释
|
||||
/**
|
||||
* 3. 提交录音文件识别请求,获取录音文件识别请求任务的ID,以供识别结果查询使用。
|
||||
*/
|
||||
String taskId = null;
|
||||
try {
|
||||
CommonResponse postResponse = client.getCommonResponse(postRequest);
|
||||
System.err.println("提交录音文件识别请求的响应:" + postResponse.getData());
|
||||
if (postResponse.getHttpStatus() == 200) {
|
||||
JSONObject result = JSONObject.parseObject(postResponse.getData());
|
||||
String statusText = result.getString(KEY_STATUS_TEXT);
|
||||
if (STATUS_SUCCESS.equals(statusText)) {
|
||||
taskId = result.getString(KEY_TASK_ID);
|
||||
}
|
||||
}
|
||||
} catch (ClientException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return taskId;
|
||||
}
|
||||
public String getFileTransResult(String taskId) {
|
||||
/**
|
||||
* 1. 创建CommonRequest,设置任务ID。
|
||||
*/
|
||||
CommonRequest getRequest = new CommonRequest();
|
||||
// 设置域名
|
||||
getRequest.setDomain(DOMAIN);
|
||||
// 设置API版本
|
||||
getRequest.setVersion(API_VERSION);
|
||||
// 设置action
|
||||
getRequest.setAction(GET_REQUEST_ACTION);
|
||||
// 设置产品名称
|
||||
getRequest.setProduct(PRODUCT);
|
||||
// 设置任务ID为查询参数
|
||||
getRequest.putQueryParameter(KEY_TASK_ID, taskId);
|
||||
// 设置为GET方式的请求
|
||||
getRequest.setMethod(MethodType.GET);
|
||||
/**
|
||||
* 2. 提交录音文件识别结果查询请求
|
||||
* 以轮询的方式进行识别结果的查询,直到服务端返回的状态描述为“SUCCESS”或错误描述,则结束轮询。
|
||||
*/
|
||||
String result = null;
|
||||
while (true) {
|
||||
try {
|
||||
CommonResponse getResponse = client.getCommonResponse(getRequest);
|
||||
System.err.println("识别查询结果:" + getResponse.getData());
|
||||
if (getResponse.getHttpStatus() != 200) {
|
||||
break;
|
||||
}
|
||||
JSONObject rootObj = JSONObject.parseObject(getResponse.getData());
|
||||
String statusText = rootObj.getString(KEY_STATUS_TEXT);
|
||||
if (STATUS_RUNNING.equals(statusText) || STATUS_QUEUEING.equals(statusText)) {
|
||||
// 继续轮询,注意设置轮询时间间隔。
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
else {
|
||||
// 状态信息为成功,返回识别结果;状态信息为异常,返回空。
|
||||
if (STATUS_SUCCESS.equals(statusText)) {
|
||||
result = rootObj.getString(KEY_RESULT);
|
||||
// 状态信息为成功,但没有识别结果,则可能是由于文件里全是静音、噪音等导致识别为空。
|
||||
if(result == null) {
|
||||
result = "";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static void main(String args[]) throws Exception {
|
||||
final String accessKeyId = System.getenv().get("ALIYUN_AK_ID");
|
||||
final String accessKeySecret = System.getenv().get("ALIYUN_AK_SECRET");
|
||||
final String appKey = System.getenv().get("NLS_APP_KEY");
|
||||
String fileLink = "https://gw.alipayobjects.com/os/bmw-prod/0574ee2e-f494-45a5-820f-63aee583045a.wav";
|
||||
TikFileTransCharacters demo = new TikFileTransCharacters(accessKeyId, accessKeySecret);
|
||||
// 第一步:提交录音文件识别请求,获取任务ID用于后续的识别结果轮询。
|
||||
String taskId = demo.submitFileTransRequest(appKey, fileLink);
|
||||
if (taskId != null) {
|
||||
System.out.println("录音文件识别请求成功,task_id: " + taskId);
|
||||
}
|
||||
else {
|
||||
System.out.println("录音文件识别请求失败!");
|
||||
return;
|
||||
}
|
||||
// 第二步:根据任务ID轮询识别结果。
|
||||
String result = demo.getFileTransResult(taskId);
|
||||
if (result != null) {
|
||||
System.out.println("录音文件识别结果查询成功:" + result);
|
||||
}
|
||||
else {
|
||||
System.out.println("录音文件识别结果查询失败!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.ai.service.tikhup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TikHupService {
|
||||
|
||||
/**
|
||||
* 获取用户主页作品数据
|
||||
* @param sec_user_id 类型
|
||||
* @param sec_user_id 用户
|
||||
* @param count 查询总数
|
||||
* @return Response
|
||||
*/
|
||||
Object fetch_user_post_videos(String type,String sec_user_id,int max_cursor, int count);
|
||||
|
||||
/**
|
||||
* 音频转文字
|
||||
* @param downloadUrl 下载地址
|
||||
* @return 语音文字
|
||||
*/
|
||||
Object videoToCharacters(String downloadUrl);
|
||||
|
||||
/**
|
||||
* 批量音频转文字
|
||||
* @param fileLinkList 音频地址
|
||||
* @return 语音文字
|
||||
*/
|
||||
Object videoToCharacters2(List<String> fileLinkList);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package cn.iocoder.yudao.module.ai.service.tikhup;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo.TikTokenVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.tikhup.TikHupMapper;
|
||||
import com.alibaba.dashscope.audio.asr.transcription.Transcription;
|
||||
import com.alibaba.dashscope.audio.asr.transcription.TranscriptionParam;
|
||||
import com.alibaba.dashscope.audio.asr.transcription.TranscriptionQueryParam;
|
||||
import com.alibaba.dashscope.audio.asr.transcription.TranscriptionResult;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.mashape.unirest.http.HttpResponse;
|
||||
import com.mashape.unirest.http.Unirest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TikHupServiceImpl implements TikHupService{
|
||||
|
||||
private final TikHupMapper tikHupMapper;
|
||||
|
||||
@Override
|
||||
public Object fetch_user_post_videos(String type,String sec_user_id, int max_cursor, int count){
|
||||
String url = StringUtils.EMPTY;
|
||||
if("xiaohongshu".equals(type)){
|
||||
url = "https://api.tikhub.io/api/v1/xiaohongshu/app/get_user_info";
|
||||
} else if("tik-web".equals(type)){
|
||||
url = "https://api.tikhub.io/api/v1/douyin/web/fetch_user_post_videos";
|
||||
} else if("tik-app".equals(type)){
|
||||
url = "https://api.tikhub.io/api/v1/douyin/app/v3/fetch_user_post_videos";
|
||||
}
|
||||
TikTokenVO tikTokenVO = tikHupMapper.getPlatformToken(url);
|
||||
String Authorization = tikTokenVO.getPlatformToken();
|
||||
try{
|
||||
Unirest.setTimeouts(0, 0);
|
||||
HttpResponse<String> response = Unirest.get(url+"?sec_user_id="+sec_user_id+"&max_cursor="+max_cursor+"&count="+count)
|
||||
.header("Authorization", "Bearer "+Authorization)
|
||||
.asString();
|
||||
if(response.getStatus() == 200){
|
||||
Long userId = SecurityFrameworkUtils.getLoginUser().getId();
|
||||
return JSON.parseObject(response.getBody());
|
||||
}
|
||||
}catch (Exception e){
|
||||
log.error("fetch_user_post_videos接口调用异常");
|
||||
}
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
private final String appKey = "sldJ4XSpYp3rKALZ ";
|
||||
private final String accessKeyId = "LTAI5tPV9Ag3csf41GZjaLTA";
|
||||
private final String accessKeySecret = "kDqlGeJTKw6tJtFYiaY8vQTFuVIQDs";
|
||||
|
||||
@Override
|
||||
public Object videoToCharacters(String fileLink){
|
||||
TikFileTransCharacters tikFileTransCharacters = new TikFileTransCharacters(accessKeyId, accessKeySecret);
|
||||
// 第一步:提交录音文件识别请求,获取任务ID用于后续的识别结果轮询。
|
||||
String taskId = tikFileTransCharacters.submitFileTransRequest(appKey, fileLink);
|
||||
if (taskId == null) {
|
||||
return CommonResult.error(500,"录音文件识别请求失败!");
|
||||
}
|
||||
// 第二步:根据任务ID轮询识别结果。
|
||||
String transResult = tikFileTransCharacters.getFileTransResult(taskId);
|
||||
if (transResult == null) {
|
||||
return CommonResult.error(501,"录音文件识别请求失败!");
|
||||
}
|
||||
return CommonResult.success(transResult);
|
||||
}
|
||||
|
||||
private final String apiKey = "sk-10c746f8cb8640738f8d6b71af699003";
|
||||
|
||||
@Override
|
||||
public Object videoToCharacters2(List<String> fileLinkList){
|
||||
// 创建转写请求参数
|
||||
TranscriptionParam param =
|
||||
TranscriptionParam.builder()
|
||||
// 若没有将API Key配置到环境变量中,需将apiKey替换为自己的API Key
|
||||
.apiKey(apiKey)
|
||||
.model("paraformer-v1")
|
||||
// “language_hints”只支持paraformer-v2模型
|
||||
.parameter("language_hints", new String[]{"zh", "en"})
|
||||
.fileUrls(fileLinkList)
|
||||
.build();
|
||||
try {
|
||||
Transcription transcription = new Transcription();
|
||||
// 提交转写请求
|
||||
TranscriptionResult result = transcription.asyncCall(param);
|
||||
log.info("RequestId: {}" ,result.getRequestId());
|
||||
// 阻塞等待任务完成并获取结果
|
||||
result = transcription.wait(
|
||||
TranscriptionQueryParam.FromTranscriptionParam(param, result.getTaskId()));
|
||||
return CommonResult.success(new GsonBuilder().setPrettyPrinting().create().toJson(result.getOutput()));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return CommonResult.error(500,"录音文件识别请求失败!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user