|
|
@@ -1,17 +1,18 @@
|
|
|
-package cn.reghao.tnb.file.app.zjob;
|
|
|
+package cn.reghao.tnb.file.app.service;
|
|
|
|
|
|
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
|
|
|
import cn.reghao.jutil.jdk.io.FileSplitter;
|
|
|
+import cn.reghao.jutil.jdk.media.FFmpegWrapper;
|
|
|
+import cn.reghao.jutil.jdk.media.model.MediaProps;
|
|
|
+import cn.reghao.jutil.jdk.media.model.VideoProps;
|
|
|
import cn.reghao.jutil.jdk.serializer.JsonConverter;
|
|
|
import cn.reghao.jutil.jdk.web.result.WebResult;
|
|
|
import cn.reghao.oss.api.dto.ServerInfo;
|
|
|
import cn.reghao.oss.api.dto.UploadFilePart;
|
|
|
-import cn.reghao.oss.api.dto.WebBody;
|
|
|
import cn.reghao.oss.api.dto.rest.UploadFileRet;
|
|
|
import cn.reghao.oss.api.dto.rest.UploadPrepare;
|
|
|
import cn.reghao.oss.api.dto.rest.UploadPrepareRet;
|
|
|
import cn.reghao.oss.api.dto.rest.UploadSample;
|
|
|
-import cn.reghao.oss.api.util.OssClientSigner;
|
|
|
import cn.reghao.oss.api.util.OssSamplingHash;
|
|
|
import cn.reghao.oss.sdk.MultiPartBodyPublisher;
|
|
|
import com.google.gson.reflect.TypeToken;
|
|
|
@@ -35,7 +36,7 @@ import java.util.*;
|
|
|
* @author reghao
|
|
|
* @date 2026-05-18 10:48:34
|
|
|
*/
|
|
|
-public class BiliOpenApiClient {
|
|
|
+public class OpenApiClient {
|
|
|
// 10MB
|
|
|
private final FileSplitter fileSplitter = new FileSplitter();
|
|
|
private final String baseUrl;
|
|
|
@@ -43,7 +44,7 @@ public class BiliOpenApiClient {
|
|
|
private final String secretKey;
|
|
|
private final HttpClient httpClient;
|
|
|
|
|
|
- public BiliOpenApiClient(String baseUrl, String accessKey, String secretKey) {
|
|
|
+ public OpenApiClient(String baseUrl, String accessKey, String secretKey) {
|
|
|
this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
|
|
this.accessKey = accessKey;
|
|
|
this.secretKey = secretKey;
|
|
|
@@ -55,7 +56,55 @@ public class BiliOpenApiClient {
|
|
|
.build();
|
|
|
}
|
|
|
|
|
|
- public UploadPrepareRet prepareUpload(int channelCode, Path filePath) throws Exception {
|
|
|
+ /**
|
|
|
+ * 计算 HMAC-SHA256 签名
|
|
|
+ */
|
|
|
+ private String calculateSign(String sk, String method, String path, String timestamp, String nonce) {
|
|
|
+ String baseString = method + "\n" + path + "\n" + timestamp + "\n" + nonce;
|
|
|
+ return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, sk).hmacHex(baseString);
|
|
|
+ }
|
|
|
+
|
|
|
+ private HttpRequest getPostRequest(String path, String jsonBody) {
|
|
|
+ //String path = "/api/open/content/vod/publish";
|
|
|
+ String timestamp = String.valueOf(System.currentTimeMillis());
|
|
|
+ String nonce = UUID.randomUUID().toString();
|
|
|
+ String method = "POST";
|
|
|
+ String sign = calculateSign(this.secretKey, method, path, timestamp, nonce);
|
|
|
+
|
|
|
+ String url = this.baseUrl + path;
|
|
|
+ return HttpRequest.newBuilder()
|
|
|
+ .uri(URI.create(url))
|
|
|
+ .timeout(Duration.ofSeconds(5)) // 请求超时
|
|
|
+ .header("Content-Type", "application/json; charset=UTF-8")
|
|
|
+ .header("X-AK", this.accessKey)
|
|
|
+ .header("X-Timestamp", timestamp)
|
|
|
+ .header("X-Nonce", nonce)
|
|
|
+ .header("X-Sign", sign)
|
|
|
+ .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ private ServerInfo getServerInfo(String channel) throws IOException, InterruptedException {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ String jsonBody = JsonConverter.objectToJson(map);
|
|
|
+
|
|
|
+ String path = String.format("/api/open/file/serverinfo/%s", channel);
|
|
|
+ HttpRequest request = getPostRequest(path, jsonBody);
|
|
|
+ // 5. 发送请求并获取响应
|
|
|
+ // 如果在外层用虚拟线程(Thread.ofVirtual().start(...))调用此方法,此处的 send() 阻塞将不会占用真实物理线程!
|
|
|
+ HttpResponse<String> response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
+ // 6. 处理响应状态码
|
|
|
+ if (response.statusCode() == 200) {
|
|
|
+ String body = response.body();
|
|
|
+ Type type = new TypeToken<WebResult<ServerInfo>>(){}.getType();
|
|
|
+ WebResult<ServerInfo> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
+ return webResult.getData();
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException("Status Code: " + response.statusCode() + ", Response: " + response.body());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private UploadPrepareRet prepareUpload(int channelCode, Path filePath) throws Exception {
|
|
|
// 1. 计算 SHA-256 (用于后端秒传校验)
|
|
|
String sha256 = OssSamplingHash.calculateFullHash(filePath);
|
|
|
String filename0 = filePath.getFileName().toString();
|
|
|
@@ -78,7 +127,7 @@ public class BiliOpenApiClient {
|
|
|
return uploadPrepareRet;
|
|
|
}
|
|
|
|
|
|
- public UploadFileRet checkSample(Path filePath, UploadPrepareRet uploadPrepareRet) throws Exception {
|
|
|
+ private UploadFileRet checkSample(Path filePath, UploadPrepareRet uploadPrepareRet) throws Exception {
|
|
|
String uploadId = uploadPrepareRet.getUploadId();
|
|
|
long offset = uploadPrepareRet.getOffset();
|
|
|
int length = uploadPrepareRet.getLength();
|
|
|
@@ -101,7 +150,7 @@ public class BiliOpenApiClient {
|
|
|
return uploadFileRet;
|
|
|
}
|
|
|
|
|
|
- public UploadFileRet uploadFilePart(int channelCode, String uploadUrl, String token, Path filePath) throws Exception {
|
|
|
+ private UploadFileRet uploadFilePart(int channelCode, String uploadUrl, String token, Path filePath) throws Exception {
|
|
|
UploadPrepareRet uploadPrepareRet = prepareUpload(channelCode, filePath);
|
|
|
if (uploadPrepareRet.isExist()) {
|
|
|
UploadFileRet uploadFileRet = checkSample(filePath, uploadPrepareRet);
|
|
|
@@ -134,7 +183,7 @@ public class BiliOpenApiClient {
|
|
|
map.put(chunkNumber, start);
|
|
|
|
|
|
int currentChunkSize = part.length;
|
|
|
- UploadFilePart uploadFilePart = new UploadFilePart(101, identifier, filename, relativePath,
|
|
|
+ UploadFilePart uploadFilePart = new UploadFilePart(channelCode, identifier, filename, relativePath,
|
|
|
totalSize, chunkSize, totalChunks, chunkNumber, currentChunkSize);
|
|
|
|
|
|
UploadFileRet uploadFileRet = postObject(uploadUrl, token, part, uploadFilePart);
|
|
|
@@ -176,10 +225,10 @@ public class BiliOpenApiClient {
|
|
|
int statusCode = httpResponse.statusCode();
|
|
|
if (statusCode == 200) {
|
|
|
String body = httpResponse.body();
|
|
|
- Type type = new TypeToken<WebBody>(){}.getType();
|
|
|
- WebBody webBody = JsonConverter.jsonToObject(body, type);
|
|
|
- if (webBody.getCode() == 0 ) {
|
|
|
- return webBody.getUploadFileRet();
|
|
|
+ Type type = new TypeToken<WebResult<UploadFileRet>>(){}.getType();
|
|
|
+ WebResult<UploadFileRet> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
+ if (webResult.getCode() == 0 ) {
|
|
|
+ return webResult.getData();
|
|
|
}
|
|
|
}
|
|
|
return null;
|
|
|
@@ -222,133 +271,152 @@ public class BiliOpenApiClient {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- public String publishVideoFile(Map<String, Object> map) throws Exception {
|
|
|
- String jsonBody = JsonConverter.objectToJson(map);
|
|
|
-
|
|
|
- String path = "/api/open/content/vod/publish/file";
|
|
|
+ private String postRequest(String path, Map<String, Object> body) {
|
|
|
+ String jsonBody = JsonConverter.objectToJson(body);
|
|
|
HttpRequest request = getPostRequest(path, jsonBody);
|
|
|
- HttpResponse<String> response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
- if (response.statusCode() == 200) {
|
|
|
- String body = response.body();
|
|
|
- Type type = new TypeToken<WebResult<String>>(){}.getType();
|
|
|
- WebResult<String> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
- if (webResult.getCode() == 0) {
|
|
|
- return webResult.getData();
|
|
|
+ try {
|
|
|
+ HttpResponse<String> response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
+ if (response.statusCode() != 200) {
|
|
|
+ throw new RuntimeException("Status Code: " + response.statusCode() + ", Response: " + response.body());
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- throw new RuntimeException("API Request Failed! Status Code: " + response.statusCode() + ", Response: " + response.body());
|
|
|
+ return response.body();
|
|
|
+ } catch (IOException | InterruptedException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public String publishVideoPost(Map<String, Object> map) throws Exception {
|
|
|
- String jsonBody = JsonConverter.objectToJson(map);
|
|
|
+ public void updateAvatar(File avatarFile) throws Exception {
|
|
|
+ ServerInfo serverInfo1 = getServerInfo("image");
|
|
|
+ UploadFileRet uploadFileRet1 = uploadSingleFile(serverInfo1.getOssUrl(), serverInfo1.getToken(), Path.of(avatarFile.getPath()));
|
|
|
+ String avatarFileId = uploadFileRet1.getUploadId();
|
|
|
|
|
|
- String path = "/api/open/content/vod/publish/post";
|
|
|
- HttpRequest request = getPostRequest(path, jsonBody);
|
|
|
- // 5. 发送请求并获取响应
|
|
|
- // 如果在外层用虚拟线程(Thread.ofVirtual().start(...))调用此方法,此处的 send() 阻塞将不会占用真实物理线程!
|
|
|
- HttpResponse<String> response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
- // 6. 处理响应状态码
|
|
|
- if (response.statusCode() == 200) {
|
|
|
- String body = response.body();
|
|
|
- Type type = new TypeToken<WebResult<String>>(){}.getType();
|
|
|
- WebResult<String> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
- if (webResult.getCode() == 0) {
|
|
|
- return webResult.getData();
|
|
|
- }
|
|
|
- }
|
|
|
+ String path = "/api/open/file/update_avatar";
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("uploadId", avatarFileId);
|
|
|
|
|
|
- throw new RuntimeException("API Request Failed! Status Code: " + response.statusCode() + ", Response: " + response.body());
|
|
|
+ String body = postRequest(path, map);
|
|
|
+ Type type = new TypeToken<WebResult<String>>(){}.getType();
|
|
|
+ WebResult<String> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
+ if (webResult.getCode() != 0) {
|
|
|
+ throw new RuntimeException("post failed: " + webResult.getMsg());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public void updateAvatar() {
|
|
|
- }
|
|
|
+ public void publishVideoPost(File coverFile, File videoFile) throws Exception {
|
|
|
+ if (coverFile == null) {
|
|
|
+ coverFile = new File(getCoverPath(videoFile));
|
|
|
+ }
|
|
|
|
|
|
- public void updateVideoCover() {
|
|
|
+ ServerInfo serverInfo1 = getServerInfo("image");
|
|
|
+ UploadFileRet uploadFileRet1 = uploadSingleFile(serverInfo1.getOssUrl(), serverInfo1.getToken(), Path.of(coverFile.getPath()));
|
|
|
+ String coverFileId = uploadFileRet1.getUploadId();
|
|
|
+
|
|
|
+ ServerInfo serverInfo2 = getServerInfo("video");
|
|
|
+ int channelCode = serverInfo2.getChannelCode();
|
|
|
+ UploadFileRet uploadFileRet2 = uploadFilePart(channelCode, serverInfo2.getOssUrl(), serverInfo2.getToken(), Path.of(videoFile.getPath()));
|
|
|
+ String videoFileId = uploadFileRet2.getUploadId();
|
|
|
+ Map<String, Object> map0 = new HashMap<>();
|
|
|
+ map0.put("videoFileId", videoFileId);
|
|
|
+ map0.put("channelCode", 101);
|
|
|
+ map0.put("filename", videoFile.getName());
|
|
|
+
|
|
|
+ String path0 = "/api/open/content/vod/publish/file";
|
|
|
+ String body = postRequest(path0, map0);
|
|
|
+ Type type = new TypeToken<WebResult<String>>(){}.getType();
|
|
|
+ WebResult<String> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
+ if (webResult.getCode() != 0) {
|
|
|
+ throw new RuntimeException("post failed: " + webResult.getMsg());
|
|
|
+ }
|
|
|
+ String videoId = webResult.getData();
|
|
|
+
|
|
|
+ String title = DateTimeConverter.format(LocalDateTime.now());
|
|
|
+ Map<String, Object> map1 = new HashMap<>();
|
|
|
+ map1.put("videoId", videoId);
|
|
|
+ map1.put("coverFileId", coverFileId);
|
|
|
+ map1.put("title", title);
|
|
|
+ map1.put("description", videoFile.getName());
|
|
|
+ map1.put("categoryPid", 11);
|
|
|
+ map1.put("categoryId", 12);
|
|
|
+ map1.put("tags", List.of("tnb"));
|
|
|
+ map1.put("scope", 2);
|
|
|
+
|
|
|
+ String path1 = "/api/open/content/vod/publish/post";
|
|
|
+ String body1 = postRequest(path1, map1);
|
|
|
+ Type type1 = new TypeToken<WebResult<String>>(){}.getType();
|
|
|
+ WebResult<String> webResult1 = JsonConverter.jsonToObject(body1, type1);
|
|
|
+ if (webResult1.getCode() != 0) {
|
|
|
+ throw new RuntimeException("post failed: " + webResult.getMsg());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public void updateVideoFile() {
|
|
|
+ private String getCoverPath(File videoFile) {
|
|
|
+ return "";
|
|
|
}
|
|
|
|
|
|
- private HttpRequest getPostRequest(String path, String jsonBody) {
|
|
|
- //String path = "/api/open/content/vod/publish";
|
|
|
- String timestamp = String.valueOf(System.currentTimeMillis());
|
|
|
- String nonce = UUID.randomUUID().toString();
|
|
|
- String method = "POST";
|
|
|
- String sign = calculateSign(this.secretKey, method, path, timestamp, nonce);
|
|
|
+ public void updateVideoCover(String videoId, File coverFile) throws Exception {
|
|
|
+ ServerInfo serverInfo1 = getServerInfo("image");
|
|
|
+ UploadFileRet uploadFileRet1 = uploadSingleFile(serverInfo1.getOssUrl(), serverInfo1.getToken(), Path.of(coverFile.getPath()));
|
|
|
+ String coverFileId = uploadFileRet1.getUploadId();
|
|
|
|
|
|
- String url = this.baseUrl + path;
|
|
|
- return HttpRequest.newBuilder()
|
|
|
- .uri(URI.create(url))
|
|
|
- .timeout(Duration.ofSeconds(5)) // 请求超时
|
|
|
- .header("Content-Type", "application/json; charset=UTF-8")
|
|
|
- .header("X-AK", this.accessKey)
|
|
|
- .header("X-Timestamp", timestamp)
|
|
|
- .header("X-Nonce", nonce)
|
|
|
- .header("X-Sign", sign)
|
|
|
- .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
|
|
|
- .build();
|
|
|
- }
|
|
|
+ String path = "/api/open/content/vod/update_cover";
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("videoId", videoId);
|
|
|
+ map.put("coverFileId", coverFileId);
|
|
|
|
|
|
- /**
|
|
|
- * 计算 HMAC-SHA256 签名
|
|
|
- */
|
|
|
- private String calculateSign(String sk, String method, String path, String timestamp, String nonce) {
|
|
|
- String baseString = method + "\n" + path + "\n" + timestamp + "\n" + nonce;
|
|
|
- return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, sk).hmacHex(baseString);
|
|
|
+ String body = postRequest(path, map);
|
|
|
+ Type type = new TypeToken<WebResult<String>>(){}.getType();
|
|
|
+ WebResult<String> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
+ if (webResult.getCode() != 0) {
|
|
|
+ throw new RuntimeException("post failed: " + webResult.getMsg());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public ServerInfo getServerInfo(String channel) throws IOException, InterruptedException {
|
|
|
+ public void updateVideoFile(String videoId, File videoFile) throws Exception {
|
|
|
+ ServerInfo serverInfo2 = getServerInfo("video");
|
|
|
+ UploadFileRet uploadFileRet2 = uploadFilePart(101, serverInfo2.getOssUrl(), serverInfo2.getToken(), Path.of(videoFile.getPath()));
|
|
|
+ String videoFileId = uploadFileRet2.getUploadId();
|
|
|
+
|
|
|
+ String path = "/api/open/content/vod/update_video";
|
|
|
Map<String, Object> map = new HashMap<>();
|
|
|
- String jsonBody = JsonConverter.objectToJson(map);
|
|
|
+ map.put("videoId", videoId);
|
|
|
+ map.put("videoFileId", videoFileId);
|
|
|
|
|
|
- String path = String.format("/api/open/file/serverinfo/%s", channel);
|
|
|
- HttpRequest request = getPostRequest(path, jsonBody);
|
|
|
- // 5. 发送请求并获取响应
|
|
|
- // 如果在外层用虚拟线程(Thread.ofVirtual().start(...))调用此方法,此处的 send() 阻塞将不会占用真实物理线程!
|
|
|
- HttpResponse<String> response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
- // 6. 处理响应状态码
|
|
|
- if (response.statusCode() == 200) {
|
|
|
- String body = response.body();
|
|
|
- Type type = new TypeToken<WebResult<ServerInfo>>(){}.getType();
|
|
|
- WebResult<ServerInfo> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
- return webResult.getData();
|
|
|
- } else {
|
|
|
- throw new RuntimeException("API Request Failed! Status Code: " + response.statusCode() + ", Response: " + response.body());
|
|
|
+ String body = postRequest(path, map);
|
|
|
+ Type type = new TypeToken<WebResult<String>>(){}.getType();
|
|
|
+ WebResult<String> webResult = JsonConverter.jsonToObject(body, type);
|
|
|
+ if (webResult.getCode() != 0) {
|
|
|
+ throw new RuntimeException("post failed: " + webResult.getMsg());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
+ long userId = 11011L;
|
|
|
String baseUrl = "https://reghao.cn";
|
|
|
String accessKey = "AK7E622DA20E9B48";
|
|
|
String secretKey = "SK89E908C80C8747E19B1ED68C7A6CA25D";
|
|
|
- BiliOpenApiClient biliOpenApiClient = new BiliOpenApiClient(baseUrl, accessKey, secretKey);
|
|
|
+ OpenApiClient openApiClient = new OpenApiClient(baseUrl, accessKey, secretKey);
|
|
|
+
|
|
|
+ File avatarFile = new File("/home/reghao/Downloads/1/avatar.jpg");
|
|
|
+ //openApiClient.updateAvatar(avatarFile);
|
|
|
|
|
|
File coverFile = new File("/home/reghao/Downloads/1/cover.jpg");
|
|
|
- ServerInfo serverInfo1 = biliOpenApiClient.getServerInfo("image");
|
|
|
- UploadFileRet uploadFileRet1 = biliOpenApiClient.uploadSingleFile(serverInfo1.getOssUrl(), serverInfo1.getToken(), Path.of(coverFile.getPath()));
|
|
|
- String coverFileId = uploadFileRet1.getUploadId();
|
|
|
+ coverFile = new File("/home/reghao/Downloads/v2-cb256237a256669399845935ff1d0e06_r.jpg");
|
|
|
+ for (int i = 0; i < 1000; i++) {
|
|
|
+ //openApiClient.updateVideoCover("6KMyx0WvmD", coverFile);
|
|
|
+ //Thread.sleep(1000);
|
|
|
+ }
|
|
|
|
|
|
- File videoFile = new File("/home/reghao/Downloads/1/video.mp4");
|
|
|
- ServerInfo serverInfo2 = biliOpenApiClient.getServerInfo("video");
|
|
|
- UploadFileRet uploadFileRet2 = biliOpenApiClient.uploadFilePart(101, serverInfo2.getOssUrl(), serverInfo2.getToken(), Path.of(videoFile.getPath()));
|
|
|
- String videoFileId = uploadFileRet2.getUploadId();
|
|
|
- Map<String, Object> map0 = new HashMap<>();
|
|
|
- map0.put("videoFileId", videoFileId);
|
|
|
- map0.put("channelCode", 101);
|
|
|
- map0.put("filename", videoFile.getName());
|
|
|
- String videoId = biliOpenApiClient.publishVideoFile(map0);
|
|
|
+ File videoFile = new File("/home/reghao/Downloads/26.mkv");
|
|
|
+ //biliOpenApiClient.updateVideoFile("", videoFile);
|
|
|
|
|
|
- String title = DateTimeConverter.format(LocalDateTime.now());
|
|
|
- Map<String, Object> map = new HashMap<>();
|
|
|
- map.put("videoId", videoId);
|
|
|
- map.put("coverFileId", coverFileId);
|
|
|
- map.put("title", title);
|
|
|
- map.put("description", videoFile.getName());
|
|
|
- map.put("categoryPid", 11);
|
|
|
- map.put("categoryId", 12);
|
|
|
- map.put("tags", List.of("tnb"));
|
|
|
- map.put("scope", 2);
|
|
|
- biliOpenApiClient.publishVideoPost(map);
|
|
|
+ MediaProps mediaProps = FFmpegWrapper.getMediaProps(videoFile.getAbsolutePath());
|
|
|
+ VideoProps videoProps = mediaProps.getVideoProps();
|
|
|
+ if (videoProps != null) {
|
|
|
+ double duration = videoProps.getDuration();
|
|
|
+ System.out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ //biliOpenApiClient.publishVideoPost(coverFile, videoFile);
|
|
|
}
|
|
|
}
|