视频剪辑上传
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
service "media/service/asr"
|
service "media/service/asr"
|
||||||
|
|
||||||
"gitea.com/red-future/common/beans"
|
"gitea.com/red-future/common/beans"
|
||||||
|
"gitea.com/red-future/common/utils"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,10 +57,23 @@ func (c *audio) ListTasks(ctx context.Context, req *dto.ListTaskReq) (res *dto.L
|
|||||||
return service.AudioTask.ListTasks(ctx, req)
|
return service.AudioTask.ListTasks(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// withUser 为 context 注入默认用户(无认证基础设施时使用)
|
// withUser 优先从请求头/X-User-Info/Token 提取用户信息,没有则用默认 admin
|
||||||
func withUser(ctx context.Context) context.Context {
|
func withUser(ctx context.Context) context.Context {
|
||||||
if ctx.Value("user") == nil {
|
if ctx.Value("user") != nil {
|
||||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user, err := utils.GetUserInfo(ctx)
|
||||||
|
if err == nil && user != nil && user.TenantId > 0 {
|
||||||
|
g.Log().Infof(ctx, "[用户信息] 从请求头解析到用户: userName=%s, tenantId=%d", user.UserName, user.TenantId)
|
||||||
|
ctx = context.WithValue(ctx, "user", user)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Debugf(ctx, "[用户信息] 解析失败(%v), 使用默认admin/tenant=1", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
service "media/service/video"
|
service "media/service/video"
|
||||||
|
|
||||||
"gitea.com/red-future/common/beans"
|
"gitea.com/red-future/common/beans"
|
||||||
|
"gitea.com/red-future/common/utils"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -126,11 +127,24 @@ func (c *video) GetConcatTask(ctx context.Context, req *dto.GetConcatTaskReq) (r
|
|||||||
return service.Concat.GetTaskResult(ctx, req.TaskID)
|
return service.Concat.GetTaskResult(ctx, req.TaskID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// withUser 为 context 注入默认用户(无认证基础设施时使用)
|
// withUser 优先从请求头/X-User-Info/Token 提取用户信息,没有则用默认 admin
|
||||||
func withUser(ctx context.Context) context.Context {
|
func withUser(ctx context.Context) context.Context {
|
||||||
if ctx.Value("user") == nil {
|
if ctx.Value("user") != nil {
|
||||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user, err := utils.GetUserInfo(ctx)
|
||||||
|
if err == nil && user != nil && user.TenantId > 0 {
|
||||||
|
g.Log().Infof(ctx, "[用户信息] 从请求头解析到用户: userName=%s, tenantId=%d", user.UserName, user.TenantId)
|
||||||
|
ctx = context.WithValue(ctx, "user", user)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Debugf(ctx, "[用户信息] 解析失败(%v), 使用默认admin/tenant=1", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,11 @@ type concatTaskDao struct{}
|
|||||||
|
|
||||||
const concatTaskTable = "concat_task"
|
const concatTaskTable = "concat_task"
|
||||||
|
|
||||||
// Insert 创建任务
|
// Insert 创建任务(排除 id 字段,让数据库自增)
|
||||||
func (d *concatTaskDao) Insert(ctx context.Context, data *entity.ConcatTask) (id int64, err error) {
|
func (d *concatTaskDao) Insert(ctx context.Context, data *entity.ConcatTask) (id int64, err error) {
|
||||||
r, err := gfdb.DB(ctx).Model(ctx, concatTaskTable).
|
r, err := gfdb.DB(ctx).Model(ctx, concatTaskTable).
|
||||||
Data(data).
|
Data(data).
|
||||||
|
FieldsEx(entity.ConcatTaskCols.Id).
|
||||||
Insert()
|
Insert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
serviceScene "media/service/scene"
|
serviceScene "media/service/scene"
|
||||||
|
|
||||||
"gitea.com/red-future/common/beans"
|
"gitea.com/red-future/common/beans"
|
||||||
|
"gitea.com/red-future/common/utils"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
"github.com/gogf/gf/v2/util/guid"
|
||||||
@@ -79,16 +80,19 @@ func (s *audioTaskService) Create(ctx context.Context, params *CreateTaskParams)
|
|||||||
g.Log().Infof(ctx, "[创建任务 %s] 文件数=%d, 模型=%s, 语言=%s, 回调=%s",
|
g.Log().Infof(ctx, "[创建任务 %s] 文件数=%d, 模型=%s, 语言=%s, 回调=%s",
|
||||||
taskID, len(params.InputData), params.Model, params.Language, params.CallbackURL)
|
taskID, len(params.InputData), params.Model, params.Language, params.CallbackURL)
|
||||||
|
|
||||||
|
// 提取调用方用户信息,传给 goroutine
|
||||||
|
user := getUserFromCtx(ctx)
|
||||||
|
|
||||||
// 异步处理
|
// 异步处理
|
||||||
go s.processTask(taskID, params.InputData, params.Model, params.Language, params.Threshold, params.CallbackURL)
|
go s.processTask(user, taskID, params.InputData, params.Model, params.Language, params.Threshold, params.CallbackURL)
|
||||||
|
|
||||||
return &dto.CreateTaskRes{TaskID: taskID}, nil
|
return &dto.CreateTaskRes{TaskID: taskID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processTask 异步处理所有URL,每个文件生成一条明细
|
// processTask 异步处理所有URL,每个文件生成一条明细
|
||||||
func (s *audioTaskService) processTask(taskID string, urls []string, model, language string, threshold float64, callbackURL string) {
|
func (s *audioTaskService) processTask(user *beans.User, taskID string, urls []string, model, language string, threshold float64, callbackURL string) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin", TenantId: 1})
|
ctx = context.WithValue(ctx, "user", user)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -231,7 +235,8 @@ func (s *audioTaskService) callback(ctx context.Context, taskID, status, errMsg,
|
|||||||
g.Log().Debugf(ctx, "[回调 %s] 回调载荷长度=%d字节, 明细条数=%d",
|
g.Log().Debugf(ctx, "[回调 %s] 回调载荷长度=%d字节, 明细条数=%d",
|
||||||
taskID, len(body), len(detailItems))
|
taskID, len(body), len(detailItems))
|
||||||
// 透传调用方的用户信息,供回调方 GetUserInfo 从 X-User-Info 头获取
|
// 透传调用方的用户信息,供回调方 GetUserInfo 从 X-User-Info 头获取
|
||||||
userJSON, _ := json.Marshal(beans.User{UserName: "admin", TenantId: 1})
|
cbUser := getUserFromCtx(ctx)
|
||||||
|
userJSON, _ := json.Marshal(cbUser)
|
||||||
g.Log().Infof(ctx, "[回调 %s] curl -X POST '%s' -H 'Content-Type: application/json' -H 'X-User-Info: %s' -d '%s'",
|
g.Log().Infof(ctx, "[回调 %s] curl -X POST '%s' -H 'Content-Type: application/json' -H 'X-User-Info: %s' -d '%s'",
|
||||||
taskID, callbackURL, string(userJSON), strings.ReplaceAll(string(body), "'", "'\\''"))
|
taskID, callbackURL, string(userJSON), strings.ReplaceAll(string(body), "'", "'\\''"))
|
||||||
|
|
||||||
@@ -316,6 +321,21 @@ func (s *audioTaskService) processSingleVideo(ctx context.Context, taskID, saveP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getUserFromCtx 从 context 提取用户信息,没有则返回默认 admin
|
||||||
|
func getUserFromCtx(ctx context.Context) *beans.User {
|
||||||
|
if u := ctx.Value("user"); u != nil {
|
||||||
|
if user, ok := u.(*beans.User); ok {
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 尝试用 common 库解析
|
||||||
|
user, err := utils.GetUserInfo(ctx)
|
||||||
|
if err == nil && user != nil {
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
return &beans.User{UserName: "admin", TenantId: 1}
|
||||||
|
}
|
||||||
|
|
||||||
// saveDetail 保存单文件明细到 transcribe_task_detail
|
// saveDetail 保存单文件明细到 transcribe_task_detail
|
||||||
func (s *audioTaskService) saveDetail(ctx context.Context, taskID string, fileIndex int, fileName, text, scenes string, audioSize int64, audioDuration, model, language, errMsg string) {
|
func (s *audioTaskService) saveDetail(ctx context.Context, taskID string, fileIndex int, fileName, text, scenes string, audioSize int64, audioDuration, model, language, errMsg string) {
|
||||||
detail := &entity.TranscribeTaskDetail{
|
detail := &entity.TranscribeTaskDetail{
|
||||||
|
|||||||
@@ -204,22 +204,40 @@ func (s *concatService) concatByFilter(ctx context.Context, ffmpegPath string, i
|
|||||||
inputArgs = append(inputArgs, "-i", p)
|
inputArgs = append(inputArgs, "-i", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 构建 filter_complex:每个视频 scale+pad 到统一尺寸,然后 concat
|
// 3. 检测每个视频是否有音频轨道及时长
|
||||||
|
hasAudio := make([]bool, n)
|
||||||
|
videoDuration := make([]float64, n)
|
||||||
|
for i, p := range inputs {
|
||||||
|
hasAudio[i] = s.hasVideoAudio(ctx, ffmpegPath, p)
|
||||||
|
videoDuration[i], _ = s.getVideoDuration(ctx, ffmpegPath, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 构建 filter_complex:每个视频 scale+pad 到统一尺寸,然后 concat
|
||||||
var filterParts []string
|
var filterParts []string
|
||||||
|
var concatInputs []string
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
filterParts = append(filterParts, fmt.Sprintf(
|
filterParts = append(filterParts, fmt.Sprintf(
|
||||||
"[%d:v]scale=%d:%d:force_original_aspect_ratio=decrease,pad=%d:%d:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30[v%d]",
|
"[%d:v]scale=%d:%d:force_original_aspect_ratio=decrease,pad=%d:%d:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30[v%d]",
|
||||||
i, maxW, maxH, maxW, maxH, i,
|
i, maxW, maxH, maxW, maxH, i,
|
||||||
))
|
))
|
||||||
|
if hasAudio[i] {
|
||||||
filterParts = append(filterParts, fmt.Sprintf(
|
filterParts = append(filterParts, fmt.Sprintf(
|
||||||
"[%d:a]aresample=44100[a%d]",
|
"[%d:a]aresample=44100[a%d]",
|
||||||
i, i,
|
i, i,
|
||||||
))
|
))
|
||||||
}
|
|
||||||
// 收集归一化后的流
|
|
||||||
var concatInputs []string
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
concatInputs = append(concatInputs, fmt.Sprintf("[v%d][a%d]", i, i))
|
concatInputs = append(concatInputs, fmt.Sprintf("[v%d][a%d]", i, i))
|
||||||
|
} else {
|
||||||
|
// 无音频轨道,生成匹配视频时长的静音音频
|
||||||
|
dur := videoDuration[i]
|
||||||
|
if dur <= 0 {
|
||||||
|
dur = 30 // 保底30秒
|
||||||
|
}
|
||||||
|
filterParts = append(filterParts, fmt.Sprintf(
|
||||||
|
"aevalsrc=0:n=2:s=44100:d=%.2f[a%d]",
|
||||||
|
dur, i,
|
||||||
|
))
|
||||||
|
concatInputs = append(concatInputs, fmt.Sprintf("[v%d][a%d]", i, i))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
filterStr := fmt.Sprintf("%s;%sconcat=n=%d:v=1:a=1[outv][outa]",
|
filterStr := fmt.Sprintf("%s;%sconcat=n=%d:v=1:a=1[outv][outa]",
|
||||||
strings.Join(filterParts, ";"),
|
strings.Join(filterParts, ";"),
|
||||||
@@ -230,8 +248,10 @@ func (s *concatService) concatByFilter(ctx context.Context, ffmpegPath string, i
|
|||||||
"-filter_complex", filterStr,
|
"-filter_complex", filterStr,
|
||||||
"-map", "[outv]",
|
"-map", "[outv]",
|
||||||
"-map", "[outa]",
|
"-map", "[outa]",
|
||||||
"-preset", "fast",
|
"-c:v", "h264_videotoolbox",
|
||||||
"-crf", "23",
|
"-b:v", "5M",
|
||||||
|
"-allow_sw", "true",
|
||||||
|
"-c:a", "aac",
|
||||||
"-y",
|
"-y",
|
||||||
output,
|
output,
|
||||||
)
|
)
|
||||||
@@ -300,6 +320,28 @@ func (s *concatService) getVideoDuration(ctx context.Context, ffmpegPath, videoP
|
|||||||
return duration, nil
|
return duration, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hasVideoAudio 检测视频文件是否有音频轨道
|
||||||
|
func (s *concatService) hasVideoAudio(ctx context.Context, ffmpegPath, videoPath string) bool {
|
||||||
|
ffprobePath := filepath.Join(filepath.Dir(ffmpegPath), "ffprobe")
|
||||||
|
if _, err := os.Stat(ffprobePath); os.IsNotExist(err) {
|
||||||
|
ffprobePath = "ffprobe"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.CommandContext(ctx, ffprobePath,
|
||||||
|
"-v", "error",
|
||||||
|
"-select_streams", "a:0",
|
||||||
|
"-show_entries", "stream=codec_type",
|
||||||
|
"-of", "default=noprint_wrappers=1:nokey=1",
|
||||||
|
videoPath,
|
||||||
|
)
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil || len(strings.TrimSpace(string(output))) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 检测视频时长,如果为0则用 aevalsrc 生成静音
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (s *concatService) getFFmpegPath() (string, error) {
|
func (s *concatService) getFFmpegPath() (string, error) {
|
||||||
ffmpegPath := g.Cfg().MustGet(context.Background(), "ffmpeg.path", "").String()
|
ffmpegPath := g.Cfg().MustGet(context.Background(), "ffmpeg.path", "").String()
|
||||||
if ffmpegPath != "" {
|
if ffmpegPath != "" {
|
||||||
@@ -359,7 +401,7 @@ func (s *concatService) UploadToMinIO(ctx context.Context, localFilePath string)
|
|||||||
client.Transport = newTransport
|
client.Transport = newTransport
|
||||||
client.SetTimeout(10 * time.Minute)
|
client.SetTimeout(10 * time.Minute)
|
||||||
|
|
||||||
// 透传认证 headers
|
// 透传认证 headers(优先从 HTTP 请求头取)
|
||||||
hasAuthHeader := false
|
hasAuthHeader := false
|
||||||
if r := g.RequestFromCtx(ctx); r != nil {
|
if r := g.RequestFromCtx(ctx); r != nil {
|
||||||
for k, v := range r.Header {
|
for k, v := range r.Header {
|
||||||
@@ -369,9 +411,10 @@ func (s *concatService) UploadToMinIO(ctx context.Context, localFilePath string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 原始请求无认证信息时,注入默认用户上下文
|
// 无 HTTP 请求时(异步 goroutine),从 context 的用户信息构造 header
|
||||||
if !hasAuthHeader {
|
if !hasAuthHeader {
|
||||||
userJSON, _ := json.Marshal(beans.User{UserName: "admin", TenantId: 1})
|
uploadUser := getUserFromCtx(ctx)
|
||||||
|
userJSON, _ := json.Marshal(uploadUser)
|
||||||
client.SetHeader("X-User-Info", string(userJSON))
|
client.SetHeader("X-User-Info", string(userJSON))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,10 +481,13 @@ func (s *concatService) CreateAsyncTask(ctx context.Context, videoURLs []string,
|
|||||||
return "", fmt.Errorf("创建任务失败: %v", err)
|
return "", fmt.Errorf("创建任务失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提取调用方用户信息,传给 goroutine
|
||||||
|
user := getUserFromCtx(ctx)
|
||||||
|
|
||||||
g.Log().Infof(ctx, "[异步拼接] 创建任务 %s, 视频数=%d, 回调=%s", taskID, len(videoURLs), callbackURL)
|
g.Log().Infof(ctx, "[异步拼接] 创建任务 %s, 视频数=%d, 回调=%s", taskID, len(videoURLs), callbackURL)
|
||||||
|
|
||||||
// 异步处理:先下载再拼接
|
// 异步处理:先下载再拼接
|
||||||
go s.processAsyncTask(taskID, videoURLs, method, upload, callbackURL)
|
go s.processAsyncTask(user, taskID, videoURLs, method, upload, callbackURL)
|
||||||
|
|
||||||
return taskID, nil
|
return taskID, nil
|
||||||
}
|
}
|
||||||
@@ -462,14 +508,27 @@ func (s *concatService) CreateAsyncTaskWithFiles(ctx context.Context, filePaths
|
|||||||
return "", fmt.Errorf("创建任务失败: %v", err)
|
return "", fmt.Errorf("创建任务失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提取调用方用户信息,传给 goroutine
|
||||||
|
user := getUserFromCtx(ctx)
|
||||||
|
|
||||||
g.Log().Infof(ctx, "[异步拼接-文件] 创建任务 %s, 文件数=%d, 回调=%s", taskID, len(filePaths), callbackURL)
|
g.Log().Infof(ctx, "[异步拼接-文件] 创建任务 %s, 文件数=%d, 回调=%s", taskID, len(filePaths), callbackURL)
|
||||||
|
|
||||||
// 异步处理:已有本地文件,直接拼接
|
// 异步处理:已有本地文件,直接拼接
|
||||||
go s.processAsyncTaskWithFiles(taskID, filePaths, method, upload, callbackURL)
|
go s.processAsyncTaskWithFiles(user, taskID, filePaths, method, upload, callbackURL)
|
||||||
|
|
||||||
return taskID, nil
|
return taskID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getUserFromCtx 从 context 中提取用户信息,如果没有则返回默认 admin
|
||||||
|
func getUserFromCtx(ctx context.Context) *beans.User {
|
||||||
|
if u := ctx.Value("user"); u != nil {
|
||||||
|
if user, ok := u.(*beans.User); ok {
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &beans.User{UserName: "admin", TenantId: 1}
|
||||||
|
}
|
||||||
|
|
||||||
// GetTaskResult 查询异步任务结果
|
// GetTaskResult 查询异步任务结果
|
||||||
func (s *concatService) GetTaskResult(ctx context.Context, taskID string) (*dto.GetConcatTaskRes, error) {
|
func (s *concatService) GetTaskResult(ctx context.Context, taskID string) (*dto.GetConcatTaskRes, error) {
|
||||||
task, err := dao.ConcatTask.GetByTaskID(ctx, taskID)
|
task, err := dao.ConcatTask.GetByTaskID(ctx, taskID)
|
||||||
@@ -484,9 +543,9 @@ func (s *concatService) GetTaskResult(ctx context.Context, taskID string) (*dto.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// processAsyncTaskWithFiles 后台处理异步拼接任务(文件上传模式,文件已在本地)
|
// processAsyncTaskWithFiles 后台处理异步拼接任务(文件上传模式,文件已在本地)
|
||||||
func (s *concatService) processAsyncTaskWithFiles(taskID string, filePaths []string, method string, upload bool, callbackURL string) {
|
func (s *concatService) processAsyncTaskWithFiles(user *beans.User, taskID string, filePaths []string, method string, upload bool, callbackURL string) {
|
||||||
bgCtx := context.Background()
|
bgCtx := context.Background()
|
||||||
bgCtx = context.WithValue(bgCtx, "user", &beans.User{UserName: "admin", TenantId: 1})
|
bgCtx = context.WithValue(bgCtx, "user", user)
|
||||||
|
|
||||||
dao.ConcatTask.UpdateRunning(bgCtx, taskID)
|
dao.ConcatTask.UpdateRunning(bgCtx, taskID)
|
||||||
|
|
||||||
@@ -514,9 +573,9 @@ func (s *concatService) processAsyncTaskWithFiles(taskID string, filePaths []str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// processAsyncTask 后台处理异步拼接任务(URL模式,需要先下载)
|
// processAsyncTask 后台处理异步拼接任务(URL模式,需要先下载)
|
||||||
func (s *concatService) processAsyncTask(taskID string, videoURLs []string, method string, upload bool, callbackURL string) {
|
func (s *concatService) processAsyncTask(user *beans.User, taskID string, videoURLs []string, method string, upload bool, callbackURL string) {
|
||||||
bgCtx := context.Background()
|
bgCtx := context.Background()
|
||||||
bgCtx = context.WithValue(bgCtx, "user", &beans.User{UserName: "admin", TenantId: 1})
|
bgCtx = context.WithValue(bgCtx, "user", user)
|
||||||
|
|
||||||
dao.ConcatTask.UpdateRunning(bgCtx, taskID)
|
dao.ConcatTask.UpdateRunning(bgCtx, taskID)
|
||||||
|
|
||||||
@@ -628,10 +687,12 @@ func (s *concatService) concatCallback(ctx context.Context, taskID, callbackURL
|
|||||||
|
|
||||||
req, _ := http.NewRequest("POST", callbackURL, bytes.NewReader(body))
|
req, _ := http.NewRequest("POST", callbackURL, bytes.NewReader(body))
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
userJSON, _ := json.Marshal(beans.User{UserName: "admin", TenantId: 1})
|
// 透传调用方用户信息
|
||||||
|
cbUser := getUserFromCtx(ctx)
|
||||||
|
userJSON, _ := json.Marshal(cbUser)
|
||||||
req.Header.Set("X-User-Info", string(userJSON))
|
req.Header.Set("X-User-Info", string(userJSON))
|
||||||
|
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
client := &http.Client{Timeout: 2 * time.Minute}
|
||||||
resp, reqErr := client.Do(req)
|
resp, reqErr := client.Do(req)
|
||||||
if reqErr != nil {
|
if reqErr != nil {
|
||||||
g.Log().Errorf(ctx, "[异步拼接回调 %s] 请求失败: %v", taskID, reqErr)
|
g.Log().Errorf(ctx, "[异步拼接回调 %s] 请求失败: %v", taskID, reqErr)
|
||||||
|
|||||||
Reference in New Issue
Block a user