mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-28 20:45:00 +02:00
apply fixes after testing
Signed-off-by: denis-tingaikin <denis.tingajkin@xored.com>
This commit is contained in:
@@ -22,61 +22,29 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/huly-stream/internal/pkg/log"
|
||||
"github.com/huly-stream/internal/pkg/resconv"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Options represents configuration for the ffmpeg command
|
||||
type Options struct {
|
||||
OuputDir string
|
||||
Resolutions []string
|
||||
Threads int
|
||||
UploadID string
|
||||
OuputDir string
|
||||
ScalingLevels []string
|
||||
Level string
|
||||
Threads int
|
||||
UploadID string
|
||||
}
|
||||
|
||||
func measure(options *Options) int64 {
|
||||
var res int64
|
||||
for _, resolution := range options.Resolutions {
|
||||
var w, h int
|
||||
var parts = strings.Split(resolution, ":")
|
||||
|
||||
if len(parts) > 1 {
|
||||
w, _ = strconv.Atoi(parts[0])
|
||||
w = max(w, 320)
|
||||
h, _ = strconv.Atoi(parts[1])
|
||||
h = max(h, 240)
|
||||
|
||||
res += int64(w) * int64(h)
|
||||
}
|
||||
}
|
||||
|
||||
return max(res, 320*240)
|
||||
}
|
||||
|
||||
func newFfmpegCommand(ctx context.Context, in io.Reader, options *Options) (*exec.Cmd, error) {
|
||||
if options == nil {
|
||||
return nil, errors.New("options should not be nil")
|
||||
}
|
||||
func newFfmpegCommand(ctx context.Context, in io.Reader, args []string) (*exec.Cmd, error) {
|
||||
if ctx == nil {
|
||||
return nil, errors.New("ctx should not be nil")
|
||||
}
|
||||
|
||||
var logger = log.FromContext(ctx).With(zap.String("func", "NewFFMpegCommand"))
|
||||
var args []string
|
||||
|
||||
if options.Resolutions == nil {
|
||||
logger.Debug("resolutions were not provided, building audio command...")
|
||||
args = BuildAudioCommand(options)
|
||||
} else {
|
||||
logger.Debug("building video command...")
|
||||
args = BuildVideoCommand(options)
|
||||
}
|
||||
var logger = log.FromContext(ctx).With(zap.String("func", "newFFMpegCommand"))
|
||||
|
||||
logger.Debug("prepared command: ", zap.Strings("args", args))
|
||||
|
||||
@@ -90,6 +58,7 @@ func newFfmpegCommand(ctx context.Context, in io.Reader, options *Options) (*exe
|
||||
|
||||
func buildCommonComamnd(opts *Options) []string {
|
||||
return []string{
|
||||
"-nostdin",
|
||||
"-threads", fmt.Sprint(opts.Threads),
|
||||
"-i", "pipe:0",
|
||||
}
|
||||
@@ -105,25 +74,25 @@ func BuildAudioCommand(opts *Options) []string {
|
||||
)
|
||||
}
|
||||
|
||||
// BuildVideoCommand returns flags for ffmpeg for video transcoding
|
||||
func BuildVideoCommand(opts *Options) []string {
|
||||
// BuildRawVideoCommand returns an extremely lightweight ffmpeg command for converting raw video without extra cost.
|
||||
func BuildRawVideoCommand(opts *Options) []string {
|
||||
return append(buildCommonComamnd(opts),
|
||||
"-c:v",
|
||||
"copy",
|
||||
"-fps_mode",
|
||||
"vfr",
|
||||
"-hls_time", "5",
|
||||
"-hls_list_size", "0",
|
||||
"-hls_segment_filename", filepath.Join(opts.OuputDir, opts.UploadID, fmt.Sprintf("%s_%s_%s.ts", opts.UploadID, "%03d", opts.Level)),
|
||||
filepath.Join(opts.OuputDir, opts.UploadID, fmt.Sprintf("%s_%s_master.m3u8", opts.UploadID, opts.Level)))
|
||||
}
|
||||
|
||||
// BuildScalingVideoCommand returns flags for ffmpeg for video scaling
|
||||
func BuildScalingVideoCommand(opts *Options) []string {
|
||||
var result = buildCommonComamnd(opts)
|
||||
|
||||
for _, res := range opts.Resolutions {
|
||||
var prefix string
|
||||
var w, h int
|
||||
var parts = strings.Split(res, ":")
|
||||
|
||||
if len(parts) > 1 {
|
||||
w, _ = strconv.Atoi(parts[0])
|
||||
h, _ = strconv.Atoi(parts[1])
|
||||
}
|
||||
w = max(w, 640)
|
||||
h = max(h, 480)
|
||||
prefix = ResolutionFromPixels(w * h)
|
||||
|
||||
for _, level := range opts.ScalingLevels {
|
||||
result = append(result,
|
||||
"-vf", fmt.Sprintf("scale=%d:%d", w, h),
|
||||
"-vf", "scale="+resconv.Resolution(level),
|
||||
"-c:v",
|
||||
"libx264",
|
||||
"-preset", "veryfast",
|
||||
@@ -131,33 +100,9 @@ func BuildVideoCommand(opts *Options) []string {
|
||||
"-g", "60",
|
||||
"-hls_time", "5",
|
||||
"-hls_list_size", "0",
|
||||
"-hls_segment_filename", filepath.Join(opts.OuputDir, fmt.Sprintf("%s_%s_%s.ts", opts.UploadID, "%03d", prefix)),
|
||||
filepath.Join(opts.OuputDir, fmt.Sprintf("%s_%s_master.m3u8", opts.UploadID, prefix)))
|
||||
"-hls_segment_filename", filepath.Join(opts.OuputDir, opts.UploadID, fmt.Sprintf("%s_%s_%s.ts", opts.UploadID, "%03d", level)),
|
||||
filepath.Join(opts.OuputDir, opts.UploadID, fmt.Sprintf("%s_%s_master.m3u8", opts.UploadID, level)))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
var resolutions = []struct {
|
||||
pixels int
|
||||
label string
|
||||
}{
|
||||
{pixels: 640 * 480, label: "320p"},
|
||||
{pixels: 1280 * 720, label: "480p"},
|
||||
{pixels: 1920 * 1080, label: "720p"},
|
||||
{pixels: 2560 * 1440, label: "1k"},
|
||||
{pixels: 3840 * 2160, label: "2k"},
|
||||
{pixels: 5120 * 2160, label: "4k"},
|
||||
{pixels: 7680 * 4320, label: "5k"},
|
||||
}
|
||||
|
||||
// ResolutionFromPixels converts pixel count to short string
|
||||
func ResolutionFromPixels(pixels int) string {
|
||||
idx := sort.Search(len(resolutions), func(i int) bool {
|
||||
return pixels < resolutions[i].pixels
|
||||
})
|
||||
if idx == len(resolutions) {
|
||||
return "8k"
|
||||
}
|
||||
return resolutions[idx].label
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user