mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-10-17 21:24:09 +08:00
封装转码请求-1
This commit is contained in:
@@ -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"))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user