mirror of
https://github.com/fxkt-tech/liv
synced 2025-09-26 20:11:20 +08:00
refactor(stream): pos instead select
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/fxkt-tech/liv/ffmpeg/filter"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/input"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/output"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -18,23 +17,27 @@ func main() {
|
||||
|
||||
// inputs
|
||||
iMain = input.WithSimple("in.mp4")
|
||||
// iSub = input.WithSimple("xx.mp4")
|
||||
|
||||
// filters
|
||||
fSplit = filter.Split(2).Use(stream.V(0))
|
||||
fOverlay = filter.Logo(50, 100, filter.LogoTopLeft).Use(fSplit.Get(0), fSplit.Get(1))
|
||||
// fSplit = filter.Split(2).Use(iMain.V(), iSub.V())
|
||||
// fOverlay = filter.Overlay(fsugar.LogoPos(50, 100, fsugar.LogoPosTopLeft)).Use(fSplit.S(0), fSplit.S(1))
|
||||
fDelogo = filter.Delogo(0, 0, 400, 400).Use(iMain.V())
|
||||
)
|
||||
|
||||
err := ffmpeg.New(
|
||||
ffmpeg.WithDebug(true),
|
||||
ffmpeg.WithDry(true),
|
||||
).AddInput(
|
||||
// iMain, iSub,
|
||||
iMain,
|
||||
).AddFilter(
|
||||
fSplit, fOverlay,
|
||||
// fSplit, fOverlay,
|
||||
fDelogo,
|
||||
).AddOutput(
|
||||
output.New(
|
||||
output.Map(fOverlay),
|
||||
output.Map(stream.Select(0, stream.MayAudio)),
|
||||
output.Map(fDelogo),
|
||||
output.Map(iMain.MayA()),
|
||||
output.Metadata("comment", "xx"),
|
||||
output.VideoCodec(codec.X264),
|
||||
output.AudioCodec(codec.Copy),
|
||||
|
@@ -61,7 +61,7 @@ func (fm *FFmpeg) Params() []string {
|
||||
params = append(params, "-y")
|
||||
}
|
||||
|
||||
params = append(params, fm.inputs.Params()...)
|
||||
params = append(params, fm.inputs.Tidy().Params()...)
|
||||
params = append(params, fm.filters.Params()...)
|
||||
params = append(params, fm.outputs.Params()...)
|
||||
return params
|
||||
|
@@ -8,45 +8,45 @@ import (
|
||||
)
|
||||
|
||||
// 音频流复制成多份
|
||||
func ASplit(n int) Filter {
|
||||
return &multiple{
|
||||
func ASplit(n int) *MultiFilter {
|
||||
return &MultiFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("asplit=%d", n),
|
||||
counts: n,
|
||||
}
|
||||
}
|
||||
|
||||
func ATempo[T constraints.Integer | constraints.Float | string](expr T) Filter {
|
||||
return &single{
|
||||
func ATempo[T constraints.Integer | constraints.Float | string](expr T) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("atempo=%v", expr),
|
||||
}
|
||||
}
|
||||
|
||||
// 音频帧显示时间戳
|
||||
func ASetPTS(expr string) Filter {
|
||||
return &single{
|
||||
func ASetPTS(expr string) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("asetpts=%s", expr),
|
||||
}
|
||||
}
|
||||
|
||||
func AMix(inputs int32) Filter {
|
||||
return &single{
|
||||
func AMix(inputs int32) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("amix=inputs=%d", inputs),
|
||||
}
|
||||
}
|
||||
|
||||
func Loudnorm(i, tp int32) Filter {
|
||||
return &single{
|
||||
func Loudnorm(i, tp int32) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("loudnorm=I=%d:TP=%d", i, tp),
|
||||
}
|
||||
}
|
||||
|
||||
func ADelay(delays int32) Filter {
|
||||
return &single{
|
||||
func ADelay(delays int32) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("adelay=delays=%ds:all=1", delays),
|
||||
}
|
||||
|
@@ -9,85 +9,69 @@ import (
|
||||
|
||||
type Filter interface {
|
||||
stream.Streamer
|
||||
Get(int) stream.Streamer
|
||||
Copy(int) Filter
|
||||
String() string
|
||||
Use(...stream.Streamer) Filter
|
||||
// Get(int) stream.Streamer
|
||||
// Copy(int) Filter
|
||||
// Use(...stream.Streamer) Filter
|
||||
}
|
||||
|
||||
// 单输出滤镜
|
||||
type single struct {
|
||||
type SingleFilter struct {
|
||||
name string
|
||||
content string
|
||||
uses []stream.Streamer
|
||||
}
|
||||
|
||||
func (s *single) Name() string {
|
||||
func (s *SingleFilter) Name(_ stream.PosFrom) string {
|
||||
if s.name == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("[%s]", s.name)
|
||||
}
|
||||
|
||||
func (s *single) Get(i int) stream.Streamer { return s }
|
||||
func (s *SingleFilter) S() stream.Streamer { return s }
|
||||
|
||||
func (s *single) Copy(index int) Filter {
|
||||
return &single{
|
||||
name: s.name,
|
||||
content: s.content,
|
||||
uses: s.uses,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *single) String() string {
|
||||
func (s *SingleFilter) String() string {
|
||||
fls := make([]string, len(s.uses))
|
||||
for i, fl := range s.uses {
|
||||
if fl != nil {
|
||||
fls[i] = fl.Name()
|
||||
fls[i] = fl.Name(stream.PosFromFilter)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s%s%s", strings.Join(fls, ""), s.content, s.Name())
|
||||
return fmt.Sprintf("%s%s%s", strings.Join(fls, ""), s.content, s.Name(stream.PosFromFilter))
|
||||
}
|
||||
|
||||
func (s *single) Use(streams ...stream.Streamer) Filter {
|
||||
func (s *SingleFilter) Use(streams ...stream.Streamer) *SingleFilter {
|
||||
s.uses = append(s.uses, streams...)
|
||||
return s
|
||||
}
|
||||
|
||||
// 多输出滤镜
|
||||
type multiple struct {
|
||||
type MultiFilter struct {
|
||||
name string
|
||||
counts int
|
||||
content string
|
||||
uses []stream.Streamer
|
||||
}
|
||||
|
||||
func (s *multiple) Name() string {
|
||||
func (s *MultiFilter) Name(_ stream.PosFrom) string {
|
||||
if s.name == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("[%s]", s.name)
|
||||
}
|
||||
|
||||
func (s *multiple) Get(i int) stream.Streamer {
|
||||
// 选择一个
|
||||
func (s *MultiFilter) S(i int) stream.Streamer {
|
||||
name := fmt.Sprintf("[%s_%d]", s.name, i)
|
||||
return stream.StreamImpl(name)
|
||||
}
|
||||
|
||||
func (s *multiple) Copy(index int) Filter {
|
||||
return &multiple{
|
||||
name: s.name,
|
||||
counts: s.counts,
|
||||
content: s.content,
|
||||
uses: s.uses,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *multiple) String() string {
|
||||
func (s *MultiFilter) String() string {
|
||||
fls := make([]string, len(s.uses))
|
||||
for i, fl := range s.uses {
|
||||
if fl != nil {
|
||||
fls[i] = fl.Name()
|
||||
fls[i] = fl.Name(stream.PosFromFilter)
|
||||
}
|
||||
}
|
||||
var names []string
|
||||
@@ -97,7 +81,7 @@ func (s *multiple) String() string {
|
||||
return fmt.Sprintf("%s%s%s", strings.Join(fls, ""), s.content, strings.Join(names, ""))
|
||||
}
|
||||
|
||||
func (s *multiple) Use(streams ...stream.Streamer) Filter {
|
||||
func (s *MultiFilter) Use(streams ...stream.Streamer) *MultiFilter {
|
||||
s.uses = append(s.uses, streams...)
|
||||
return s
|
||||
}
|
||||
@@ -106,11 +90,6 @@ func (s *multiple) Use(streams ...stream.Streamer) Filter {
|
||||
|
||||
type Filters []Filter
|
||||
|
||||
// func (filters Filters) RefInput() Filters {
|
||||
|
||||
// return filters
|
||||
// }
|
||||
|
||||
func (filters Filters) Params() (params []string) {
|
||||
txt := filters.String()
|
||||
if txt == "" {
|
||||
|
29
ffmpeg/filter/fsugar/video.go
Normal file
29
ffmpeg/filter/fsugar/video.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package fsugar
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fxkt-tech/liv/ffmpeg/filter"
|
||||
)
|
||||
|
||||
const (
|
||||
LogoPosTopLeft = "TopLeft"
|
||||
LogoPosTopRight = "TopRight"
|
||||
LogoPosBottomRight = "BottomRight"
|
||||
LogoPosBottomLeft = "BottomLeft"
|
||||
)
|
||||
|
||||
// logo位置
|
||||
func LogoPos[T filter.Expr](dx, dy T, pos string) (string, string) {
|
||||
switch pos {
|
||||
case LogoPosTopLeft:
|
||||
return fmt.Sprintf("%v", dx), fmt.Sprintf("%v", dy)
|
||||
case LogoPosTopRight:
|
||||
return fmt.Sprintf("W-w-%v", dx), fmt.Sprintf("%v", dy)
|
||||
case LogoPosBottomRight:
|
||||
return fmt.Sprintf("W-w-%v", dx), fmt.Sprintf("H-h-%v", dy)
|
||||
case LogoPosBottomLeft:
|
||||
return fmt.Sprintf("%v", dx), fmt.Sprintf("H-h-%v", dy)
|
||||
}
|
||||
return "", ""
|
||||
}
|
@@ -9,52 +9,32 @@ import (
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
type LogoPos string
|
||||
type Expr interface {
|
||||
Numb | ~string
|
||||
}
|
||||
|
||||
const (
|
||||
LogoTopLeft LogoPos = "TopLeft"
|
||||
LogoTopRight LogoPos = "TopRight"
|
||||
LogoBottomRight LogoPos = "BottomRight"
|
||||
LogoBottomLeft LogoPos = "BottomLeft"
|
||||
)
|
||||
|
||||
// 贴logo
|
||||
func Logo(dx, dy int64, pos LogoPos) Filter {
|
||||
var content string
|
||||
switch pos {
|
||||
case LogoTopLeft:
|
||||
content = fmt.Sprintf("overlay=%d:%d", dx, dy)
|
||||
case LogoTopRight:
|
||||
content = fmt.Sprintf("overlay=W-w-%d:%d", dx, dy)
|
||||
case LogoBottomRight:
|
||||
content = fmt.Sprintf("overlay=W-w-%d:H-h-%d", dx, dy)
|
||||
case LogoBottomLeft:
|
||||
content = fmt.Sprintf("overlay=%d:H-h-%d", dx, dy)
|
||||
}
|
||||
return &single{
|
||||
name: naming.Default.Gen(),
|
||||
content: content,
|
||||
}
|
||||
type Numb interface {
|
||||
~int32 | ~int
|
||||
}
|
||||
|
||||
// 一个图像覆盖另一个图像
|
||||
func Overlay[T constraints.Signed | string](dx, dy T) Filter {
|
||||
return &single{
|
||||
func Overlay[T Expr](dx, dy T) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("overlay=%v:%v", dx, dy),
|
||||
}
|
||||
}
|
||||
|
||||
// 一个图像覆盖另一个图像(可激活某一时间段)
|
||||
func OverlayWithEnable[T constraints.Signed | string](dx, dy T, enable string) Filter {
|
||||
return &single{
|
||||
// Deprecated: 一个图像覆盖另一个图像(可激活某一时间段)
|
||||
func OverlayWithEnable[T Expr](dx, dy T, enable string) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("overlay=%v:%v:enable='%s'", dx, dy, enable),
|
||||
}
|
||||
}
|
||||
|
||||
// 缩放
|
||||
func Scale[T int32 | int | string](w, h T) Filter {
|
||||
func Scale[T Expr](w, h T) *SingleFilter {
|
||||
var ww, hh any = w, h
|
||||
switch ww.(type) {
|
||||
case int32:
|
||||
@@ -64,22 +44,22 @@ func Scale[T int32 | int | string](w, h T) Filter {
|
||||
case string:
|
||||
ww, hh = w, h
|
||||
}
|
||||
return &single{
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("scale=%v:%v", ww, hh),
|
||||
}
|
||||
}
|
||||
|
||||
// func UnsopportedSimple(fstr string) Filter {
|
||||
// return &single{
|
||||
// func UnsopportedSimple(fstr string) *SingleFilter {
|
||||
// return &SingleFilter{
|
||||
// name: naming.Default.Gen(),
|
||||
// content: fstr,
|
||||
// }
|
||||
// }
|
||||
|
||||
// 绿幕抠像
|
||||
func Chromakey(color string, similarity, blend float32) Filter {
|
||||
return &single{
|
||||
func Chromakey(color string, similarity, blend float32) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf(
|
||||
"chromakey=%s:%.2f:%.2f",
|
||||
@@ -89,8 +69,8 @@ func Chromakey(color string, similarity, blend float32) Filter {
|
||||
}
|
||||
|
||||
// 创建一个底版
|
||||
func Color(c string, w, h int32, d float32) Filter {
|
||||
return &single{
|
||||
func Color(c string, w, h int32, d float32) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf(
|
||||
"color=c=%s:s=%d*%d:d=%.2f",
|
||||
@@ -100,35 +80,26 @@ func Color(c string, w, h int32, d float32) Filter {
|
||||
}
|
||||
|
||||
// 裁切
|
||||
func Crop(x, y, w, h int32) Filter {
|
||||
return &single{
|
||||
func Crop[T Expr](x, y, w, h T) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf(
|
||||
"crop=%d:%d:%d:%d",
|
||||
"crop=%v:%v:%v:%v",
|
||||
x, y, w, h,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// 视频帧显示时间戳
|
||||
func SetPTS(expr string) Filter {
|
||||
return &single{
|
||||
func SetPTS(expr string) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("setpts=%s", expr),
|
||||
}
|
||||
}
|
||||
|
||||
// 视频流复制成多份
|
||||
func Split(n int) Filter {
|
||||
return &multiple{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("split=%d", n),
|
||||
counts: n,
|
||||
}
|
||||
}
|
||||
|
||||
// 截取某一时间段
|
||||
func Trim(s, e float64) Filter {
|
||||
func Trim(s, e float64) *SingleFilter {
|
||||
var ps []string
|
||||
if s != 0 {
|
||||
ps = append(ps, fmt.Sprintf("start=%f", s))
|
||||
@@ -141,15 +112,15 @@ func Trim(s, e float64) Filter {
|
||||
if psstr != "" {
|
||||
eqs = "="
|
||||
}
|
||||
return &single{
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("trim%s%s", eqs, psstr),
|
||||
}
|
||||
}
|
||||
|
||||
// 擦除logo
|
||||
func Delogo(x, y, w, h int64) Filter {
|
||||
return &single{
|
||||
// Deprecated: 擦除logo
|
||||
func Delogo_Old(x, y, w, h int32) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("delogo=%d:%d:%d:%d",
|
||||
x+1, y+1, w-2, h-2,
|
||||
@@ -157,29 +128,50 @@ func Delogo(x, y, w, h int64) Filter {
|
||||
}
|
||||
}
|
||||
|
||||
func Select(expr string) Filter {
|
||||
return &single{
|
||||
// 遮标
|
||||
func Delogo[T Numb](x, y, w, h T) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("delogo=x=%v:y=%v:w=%v:h=%v",
|
||||
x+1, y+1, w-2, h-2,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func Select(expr string) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("select=%s", expr),
|
||||
}
|
||||
}
|
||||
|
||||
func FPS[N, D constraints.Integer | constraints.Float](fps *math.Rational[N, D]) Filter {
|
||||
func FPS[N, D constraints.Integer | constraints.Float](fps *math.Rational[N, D]) *SingleFilter {
|
||||
var s string
|
||||
if fps.Den == 0 {
|
||||
s = "source_fps"
|
||||
} else {
|
||||
s = fmt.Sprintf("%v/%v", fps.Num, fps.Den)
|
||||
}
|
||||
return &single{
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("fps=fps=%s", s),
|
||||
}
|
||||
}
|
||||
|
||||
func Tile(xlen, ylen int32) Filter {
|
||||
return &single{
|
||||
func Tile(xlen, ylen int32) *SingleFilter {
|
||||
return &SingleFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("tile=%d*%d", xlen, ylen),
|
||||
}
|
||||
}
|
||||
|
||||
// multi
|
||||
|
||||
// 视频流复制成多份
|
||||
func Split(n int) *MultiFilter {
|
||||
return &MultiFilter{
|
||||
name: naming.Default.Gen(),
|
||||
content: fmt.Sprintf("split=%d", n),
|
||||
counts: n,
|
||||
}
|
||||
}
|
||||
|
@@ -3,11 +3,13 @@ package input
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fxkt-tech/liv/ffmpeg/stream"
|
||||
)
|
||||
|
||||
// Input is common input info.
|
||||
type Input struct {
|
||||
index int
|
||||
idx int
|
||||
|
||||
cv string
|
||||
r string
|
||||
@@ -48,6 +50,22 @@ func WithTime(ss, t float64, i string) *Input {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Input) V() stream.Streamer {
|
||||
return &InputStream{input: i, s: stream.Video}
|
||||
}
|
||||
|
||||
func (i *Input) A() stream.Streamer {
|
||||
return &InputStream{input: i, s: stream.Audio}
|
||||
}
|
||||
|
||||
func (i *Input) MayV() stream.Streamer {
|
||||
return &InputStream{input: i, s: stream.MayVideo}
|
||||
}
|
||||
|
||||
func (i *Input) MayA() stream.Streamer {
|
||||
return &InputStream{input: i, s: stream.MayAudio}
|
||||
}
|
||||
|
||||
func (i *Input) Params() (params []string) {
|
||||
if i.r != "" {
|
||||
params = append(params, "-r", i.r)
|
||||
@@ -92,3 +110,27 @@ func (inputs Inputs) Params() (params []string) {
|
||||
func (inputs Inputs) String() string {
|
||||
return strings.Join(inputs.Params(), " ")
|
||||
}
|
||||
|
||||
func (inputs Inputs) Tidy() Inputs {
|
||||
for i, input := range inputs {
|
||||
input.idx = i
|
||||
}
|
||||
return inputs
|
||||
}
|
||||
|
||||
// stream
|
||||
|
||||
// input型stream
|
||||
type InputStream struct {
|
||||
input *Input
|
||||
s stream.Stream
|
||||
}
|
||||
|
||||
func (s *InputStream) Name(pf stream.PosFrom) string {
|
||||
switch pf {
|
||||
case stream.PosFromOutput:
|
||||
return fmt.Sprintf("%d:%s", s.input.idx, s.s)
|
||||
default:
|
||||
return fmt.Sprintf("[%d:%s]", s.input.idx, s.s)
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ func New(opts ...Option) *Output {
|
||||
func (o *Output) Params() (params []string) {
|
||||
if len(o.maps) != 0 {
|
||||
for _, m := range o.maps {
|
||||
params = append(params, "-map", m.Name())
|
||||
params = append(params, "-map", m.Name(stream.PosFromOutput))
|
||||
}
|
||||
}
|
||||
if o.cv != "" {
|
||||
|
@@ -14,13 +14,22 @@ const (
|
||||
MayVideo Stream = "v?"
|
||||
)
|
||||
|
||||
type PosFrom string
|
||||
|
||||
const (
|
||||
PosFromInput PosFrom = "input"
|
||||
PosFromFilter PosFrom = "filter"
|
||||
PosFromOutput PosFrom = "output"
|
||||
)
|
||||
|
||||
type Streamer interface {
|
||||
Name() string
|
||||
Name(PosFrom) string
|
||||
}
|
||||
|
||||
// 常量型stream
|
||||
type StreamImpl string
|
||||
|
||||
func (s StreamImpl) Name() string {
|
||||
func (s StreamImpl) Name(pf PosFrom) string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
@@ -30,10 +39,10 @@ func Select(idx int, s Stream) Streamer {
|
||||
|
||||
// 从input中选择视频流,仅用于filter中
|
||||
func V(i int) Streamer {
|
||||
return StreamImpl(fmt.Sprintf("[%d:v]", i))
|
||||
return StreamImpl(fmt.Sprintf("[%d:%s]", i, Video))
|
||||
}
|
||||
|
||||
// 从input中选择音频流,仅用于filter中
|
||||
func A(i int) Streamer {
|
||||
return StreamImpl(fmt.Sprintf("[%d:a]", i))
|
||||
return StreamImpl(fmt.Sprintf("[%d:%s]", i, Audio))
|
||||
}
|
||||
|
25
transcode.go
25
transcode.go
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/fxkt-tech/liv/ffmpeg"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/codec"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/filter"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/filter/fsugar"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/input"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/output"
|
||||
"github.com/fxkt-tech/liv/ffmpeg/stream"
|
||||
@@ -58,14 +59,14 @@ func (tc *Transcode) SimpleMP4(ctx context.Context, params *TranscodeParams) err
|
||||
filters = append(filters, fsplit)
|
||||
for i, sub := range params.Subs {
|
||||
// 处理filter
|
||||
lastFilter := fsplit.Copy(i)
|
||||
lastFilter := fsplit.S(i)
|
||||
|
||||
// 处理遮标
|
||||
if delogos := sub.Filters.Delogo; len(delogos) > 0 {
|
||||
for _, delogo := range delogos {
|
||||
fdelogo := filter.Delogo(
|
||||
int64(delogo.Rect.X), int64(delogo.Rect.Y),
|
||||
int64(delogo.Rect.W), int64(delogo.Rect.H),
|
||||
int32(delogo.Rect.X), int32(delogo.Rect.Y),
|
||||
int32(delogo.Rect.W), int32(delogo.Rect.H),
|
||||
).Use(lastFilter)
|
||||
filters = append(filters, fdelogo)
|
||||
lastFilter = fdelogo
|
||||
@@ -97,7 +98,7 @@ func (tc *Transcode) SimpleMP4(ctx context.Context, params *TranscodeParams) err
|
||||
} else {
|
||||
finalLogoStream = logoStream
|
||||
}
|
||||
flogo := filter.Logo(int64(logo.Dx), int64(logo.Dy), filter.LogoPos(logo.Pos)).
|
||||
flogo := filter.Overlay(fsugar.LogoPos(int32(logo.Dx), int32(logo.Dy), logo.Pos)).
|
||||
Use(lastFilter, finalLogoStream)
|
||||
filters = append(filters, flogo)
|
||||
inputs = append(inputs, input.WithSimple(logo.File))
|
||||
@@ -167,7 +168,7 @@ func (tc *Transcode) SimpleMP3(ctx context.Context, params *TranscodeParams) err
|
||||
filters = append(filters, fsplit)
|
||||
for i, sub := range params.Subs {
|
||||
// 处理filter
|
||||
lastFilter := fsplit.Copy(i)
|
||||
lastFilter := fsplit.S(i)
|
||||
|
||||
// 处理output
|
||||
outputOpts := []output.Option{
|
||||
@@ -212,12 +213,12 @@ func (tc *Transcode) SimpleJPEG(ctx context.Context, params *TranscodeParams) er
|
||||
filters = append(filters, fsplit)
|
||||
for i, sub := range params.Subs {
|
||||
// 处理filter
|
||||
lastFilter := fsplit.Copy(i)
|
||||
lastFilter := fsplit.S(i)
|
||||
|
||||
// 处理遮标
|
||||
if delogos := sub.Filters.Delogo; len(delogos) > 0 {
|
||||
for _, delogo := range delogos {
|
||||
fdelogo := filter.Delogo(int64(delogo.Rect.X), int64(delogo.Rect.Y), int64(delogo.Rect.W), int64(delogo.Rect.H)).Use(lastFilter)
|
||||
fdelogo := filter.Delogo(int32(delogo.Rect.X), int32(delogo.Rect.Y), int32(delogo.Rect.W), int32(delogo.Rect.H)).Use(lastFilter)
|
||||
filters = append(filters, fdelogo)
|
||||
lastFilter = fdelogo
|
||||
}
|
||||
@@ -233,7 +234,7 @@ func (tc *Transcode) SimpleJPEG(ctx context.Context, params *TranscodeParams) er
|
||||
// 添加水印
|
||||
if logos := sub.Filters.Logo; len(logos) > 0 {
|
||||
for _, logo := range logos {
|
||||
flogo := filter.Logo(int64(logo.Dx), int64(logo.Dy), filter.LogoPos(logo.Pos)).Use(lastFilter)
|
||||
flogo := filter.Overlay(fsugar.LogoPos(int32(logo.Dx), int32(logo.Dy), logo.Pos)).Use(lastFilter)
|
||||
filters = append(filters, flogo)
|
||||
inputs = append(inputs, input.WithSimple(logo.File))
|
||||
lastFilter = flogo
|
||||
@@ -322,7 +323,7 @@ func (tc *Transcode) SimpleHLS(ctx context.Context, params *TranscodeSimpleHLSPa
|
||||
if delogos := params.Filters.Delogo; len(delogos) > 0 {
|
||||
for _, delogo := range delogos {
|
||||
fdelogo := filter.Delogo(
|
||||
int64(delogo.Rect.X), int64(delogo.Rect.Y), int64(delogo.Rect.W), int64(delogo.Rect.H)).
|
||||
int32(delogo.Rect.X), int32(delogo.Rect.Y), int32(delogo.Rect.W), int32(delogo.Rect.H)).
|
||||
Use(lastFilter)
|
||||
filters = append(filters, fdelogo)
|
||||
lastFilter = fdelogo
|
||||
@@ -351,7 +352,7 @@ func (tc *Transcode) SimpleHLS(ctx context.Context, params *TranscodeSimpleHLSPa
|
||||
} else {
|
||||
finalLogoStream = logoStream
|
||||
}
|
||||
flogo := filter.Logo(int64(logo.Dx), int64(logo.Dy), filter.LogoPos(logo.Pos)).
|
||||
flogo := filter.Overlay(fsugar.LogoPos(int32(logo.Dx), int32(logo.Dy), logo.Pos)).
|
||||
Use(lastFilter, finalLogoStream)
|
||||
filters = append(filters, flogo)
|
||||
inputs = append(inputs, input.WithSimple(logo.File))
|
||||
@@ -424,7 +425,7 @@ func (tc *Transcode) SimpleTS(ctx context.Context, params *TranscodeSimpleTSPara
|
||||
if delogos := params.Filters.Delogo; len(delogos) > 0 {
|
||||
for _, delogo := range delogos {
|
||||
fdelogo := filter.Delogo(
|
||||
int64(delogo.Rect.X), int64(delogo.Rect.Y), int64(delogo.Rect.W), int64(delogo.Rect.H)).
|
||||
int32(delogo.Rect.X), int32(delogo.Rect.Y), int32(delogo.Rect.W), int32(delogo.Rect.H)).
|
||||
Use(lastFilter)
|
||||
filters = append(filters, fdelogo)
|
||||
lastFilter = fdelogo
|
||||
@@ -453,7 +454,7 @@ func (tc *Transcode) SimpleTS(ctx context.Context, params *TranscodeSimpleTSPara
|
||||
} else {
|
||||
finalLogoStream = logoStream
|
||||
}
|
||||
flogo := filter.Logo(int64(logo.Dx), int64(logo.Dy), filter.LogoPos(logo.Pos)).
|
||||
flogo := filter.Overlay(fsugar.LogoPos(int32(logo.Dx), int32(logo.Dy), logo.Pos)).
|
||||
Use(lastFilter, finalLogoStream)
|
||||
filters = append(filters, flogo)
|
||||
inputs = append(inputs, input.WithSimple(logo.File))
|
||||
|
Reference in New Issue
Block a user