封装转码请求-1

This commit is contained in:
banshan
2024-09-27 22:14:39 +08:00
parent c08514d20e
commit 0309298ab0

View File

@@ -2,19 +2,23 @@ package plugin_transcode
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json"
"fmt" "fmt"
"m7s.live/m7s/v5/pkg/config"
transcode "m7s.live/m7s/v5/plugin/transcode/pkg"
"net/http" "net/http"
"net/url"
"os" "os"
"path"
"strconv" "strconv"
"strings" "strings"
"m7s.live/m7s/v5/pkg/config"
transcode "m7s.live/m7s/v5/plugin/transcode/pkg"
) )
type OverlayConfig struct { type OverlayConfig struct {
OverlayStream string `json:"overlay_stream"` // 叠加流 可为空 OverlayStream string `json:"overlay_stream"` // 叠加流 可为空
OverlayRegion string `json:"region"` //x,y,w,h 可为空,所有区域 OverlayRegion string `json:"region"` //x,y,w,h 可为空,所有区域
OverlayImage string `json:"image"` // 图片 base64 可为空 OverlayImage string `json:"image"` // 图片 base64 可为空 如果图片和视频流都有,则使用图片
OverlayPosition string `json:"overlay_position"` //位置 x,y OverlayPosition string `json:"overlay_position"` //位置 x,y
Text string `json:"text"` // 文字 Text string `json:"text"` // 文字
FontName string `json:"font_name"` //字体文件名 FontName string `json:"font_name"` //字体文件名
@@ -25,9 +29,12 @@ type OverlayConfig struct {
} }
type OnDemandTrans struct { type OnDemandTrans struct {
SrcStream string `json:"src_stream"` SrcStream string `json:"src_stream"` //原始流
DstStream string `json:"dst_stream"` DstStream string `json:"dst_stream"` //输出流
OverlayConfigs []*OverlayConfig `json:"overlay_config"` OverlayConfigs []*OverlayConfig `json:"overlay_config"`
Encodec string `json:"encodec"`
Decodec string `json:"decodec"`
Scale string `json:"scale"`
} }
func createTmpImage(image string) (string, error) { func createTmpImage(image string) (string, error) {
@@ -79,61 +86,125 @@ func rgbToHex(FontColor string) (string, error) {
} }
} }
func parseCoordinates(coordString string) (string, error) {
if coordString == "" {
return "", nil
}
coords := strings.Split(coordString, ",")
if len(coords) != 2 {
return "", fmt.Errorf("坐标格式不正确,应该是 x,y")
}
x := strings.TrimSpace(coords[0])
y := strings.TrimSpace(coords[1])
return fmt.Sprintf("x=%s:y=%s", x, y), nil
}
func parseCrop(cropString string) (string, error) {
if cropString == "" {
return "", nil
}
cropValues := strings.Split(cropString, ",")
if len(cropValues) != 4 {
return "", fmt.Errorf("裁剪参数格式不正确,应该是 x,y,w,h")
}
x := strings.TrimSpace(cropValues[0])
y := strings.TrimSpace(cropValues[1])
w := strings.TrimSpace(cropValues[2])
h := strings.TrimSpace(cropValues[3])
return fmt.Sprintf("crop=%s:%s:%s:%s", x, y, w, h), nil
}
func (t *TranscodePlugin) api_transcode_start(w http.ResponseWriter, r *http.Request) { func (t *TranscodePlugin) api_transcode_start(w http.ResponseWriter, r *http.Request) {
//解析出 OverlayConfigs //解析出 OverlayConfigs
//var trans OnDemandTrans var transReq OnDemandTrans
//err := json.NewDecoder(r.Body).Decode(&trans) err := json.NewDecoder(r.Body).Decode(&transReq)
//if err != nil { if err != nil {
// http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
// return return
//} }
////循环判断 var inputs []string
//for _, overlayConfig := range trans.OverlayConfigs { var filters string
// if overlayConfig.OverlayImage == "" || overlayConfig.Text == "" { //循环判断
// http.Error(w, "image_base64 and text is required", http.StatusBadRequest) for _, overlayConfig := range transReq.OverlayConfigs {
// return if overlayConfig.OverlayImage == "" && overlayConfig.Text == "" && overlayConfig.OverlayStream == "" {
// } http.Error(w, "image_base64 and text is required", http.StatusBadRequest)
// filePath, err := createTmpImage(overlayConfig.OverlayImage) return
// if err != nil { }
// http.Error(w, err.Error(), http.StatusBadRequest) filePath, err := createTmpImage(overlayConfig.OverlayImage)
// return if err != nil {
// } http.Error(w, err.Error(), http.StatusBadRequest)
// overlayConfig.imagePath = filePath return
// overlayConfig.FontName = "./font/" + overlayConfig.FontName }
// overlayConfig.imagePath = filePath
// // 将 r,g,b 颜色字符串转换为十六进制颜色
// overlayConfig.FontColor, err = rgbToHex(overlayConfig.FontColor)
// if err != nil {
// http.Error(w, "FontColor 格式不正确", http.StatusBadRequest)
// return
// }
//}
// 1、先叠加不用管参数 // 将 r,g,b 颜色字符串转换为十六进制颜色
// 2、参数处理 overlayConfig.FontColor, err = rgbToHex(overlayConfig.FontColor)
if err != nil {
http.Error(w, "FontColor 格式不正确", http.StatusBadRequest)
return
}
//坐标
overlayConfig.OverlayPosition, err = parseCoordinates(overlayConfig.OverlayPosition)
if err != nil {
http.Error(w, "OverlayPosition 格式不正确", http.StatusBadRequest)
return
}
overlayConfig.OverlayRegion, err = parseCrop(overlayConfig.OverlayRegion)
if err != nil {
http.Error(w, "OverlayRegion 格式不正确", http.StatusBadRequest)
return
}
overlayConfig.TextPosition, err = parseCoordinates(overlayConfig.TextPosition)
if err != nil {
http.Error(w, "TextPosition 格式不正确", http.StatusBadRequest)
return
}
if overlayConfig.imagePath != "" {
inputs = append(inputs, overlayConfig.imagePath)
} else if overlayConfig.OverlayStream != "" {
inputs = append(inputs, overlayConfig.OverlayStream)
}
filters += ""
}
//ffmpeg -i input_video.mp4 -i input_image.png -filter_complex "[1:v]drawtext=fontfile=/path/to/font.ttf:fontsize=24:fontcolor=white:x=10:y=10:text='Your Text Here'[img];[0:v][img]overlay=x=100:y=100:enable='between(t,0,5)'" output_video.mp4 //ffmpeg -i input_video.mp4 -i input_image.png -filter_complex "[1:v]drawtext=fontfile=/path/to/font.ttf:fontsize=24:fontcolor=white:x=10:y=10:text='Your Text Here'[img];[0:v][img]overlay=x=100:y=100:enable='between(t,0,5)'" output_video.mp4
// trans := transcode.NewTransform() // trans := transcode.NewTransform()
// trans.(*transcode.Transformer).Start() // trans.(*transcode.Transformer).Start()
//把 overlayconfig 转为 filter_complex
transformer := t.Meta.Transformer() transformer := t.Meta.Transformer()
trans := transformer.(*transcode.Transformer) transcode := transformer.(*transcode.Transformer)
var cfg config.Transform var cfg config.Transform
cfg.Output = []struct { // 解析URL路径
Target string `desc:"转码目标"` targetURL := transReq.DstStream
StreamPath string parsedURL, err := url.Parse(targetURL)
Conf any if err != nil {
}{ http.Error(w, "无效的目标URL", http.StatusBadRequest)
return
}
// 获取路径部分并清理
streamPath := path.Clean(parsedURL.Path)
// 去掉开头的斜杠
streamPath = strings.TrimPrefix(streamPath, "/")
conf := strings.Join(inputs, " ") + filters + transReq.Scale + transReq.Encodec
cfg.Output = []config.TransfromOutput{
{ {
Target: "rtmp://127.0.0.1:1935/live/test/h264", Target: targetURL,
StreamPath: "live/test/h264", StreamPath: streamPath,
Conf: "-loglevel debug -s 480x200 -c:a copy -c:v h264", Conf: conf,
}, },
} }
t.Transform("live/test", cfg)
fmt.Println(trans, cfg) t.Transform(transReq.SrcStream, cfg)
fmt.Println(transcode, cfg)
w.Write([]byte("ok")) w.Write([]byte("ok"))
} }