Custom video transcode FPS
This commit is contained in:
@@ -54,7 +54,7 @@ Build and push this container to ghcr
|
|||||||
- [ ] change from Audio -> Video
|
- [ ] change from Audio -> Video
|
||||||
- [x] Provide a better name for downloaded files
|
- [x] Provide a better name for downloaded files
|
||||||
- [x] Environment variable to control whether "Secure" flag set on cookie
|
- [x] Environment variable to control whether "Secure" flag set on cookie
|
||||||
- [ ] Allow custom FPS for video transcode
|
- [x] Allow custom FPS for video transcode
|
||||||
- [ ] Provide an about page
|
- [ ] Provide an about page
|
||||||
- `ffmpeg` version
|
- `ffmpeg` version
|
||||||
- `yt-dlp` version
|
- `yt-dlp` version
|
||||||
|
@@ -486,13 +486,14 @@ func addAudioTranscode(mediaId, originalId, bitrate uint, srcKind string) {
|
|||||||
db.Create(&t)
|
db.Create(&t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addVideoTranscode(videoId, originalId, targetHeight uint) {
|
func addVideoTranscode(videoId, originalId, targetHeight uint, targetFPS float64) {
|
||||||
t := Transcode{
|
t := Transcode{
|
||||||
SrcID: videoId,
|
SrcID: videoId,
|
||||||
OriginalID: originalId,
|
OriginalID: originalId,
|
||||||
SrcKind: "video",
|
SrcKind: "video",
|
||||||
DstKind: "video",
|
DstKind: "video",
|
||||||
Height: targetHeight,
|
Height: targetHeight,
|
||||||
|
FPS: targetFPS,
|
||||||
TimeSubmit: time.Now(),
|
TimeSubmit: time.Now(),
|
||||||
Status: "pending",
|
Status: "pending",
|
||||||
}
|
}
|
||||||
@@ -532,7 +533,7 @@ func processOriginal(originalID uint) {
|
|||||||
// create video transcodes
|
// create video transcodes
|
||||||
for _, targetHeight := range []uint{480, 240, 144} {
|
for _, targetHeight := range []uint{480, 240, 144} {
|
||||||
if targetHeight <= video.Height {
|
if targetHeight <= video.Height {
|
||||||
addVideoTranscode(video.ID, originalID, targetHeight)
|
addVideoTranscode(video.ID, originalID, targetHeight, video.FPS)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1045,6 +1046,7 @@ func deleteAudioHandler(c echo.Context) error {
|
|||||||
func transcodeToVideoHandler(c echo.Context) error {
|
func transcodeToVideoHandler(c echo.Context) error {
|
||||||
originalId, _ := strconv.ParseUint(c.FormValue("original_id"), 10, 32)
|
originalId, _ := strconv.ParseUint(c.FormValue("original_id"), 10, 32)
|
||||||
height, _ := strconv.ParseUint(c.FormValue("height"), 10, 32)
|
height, _ := strconv.ParseUint(c.FormValue("height"), 10, 32)
|
||||||
|
fps, _ := strconv.ParseFloat(c.FormValue("fps"), 64)
|
||||||
referrer := c.Request().Referer()
|
referrer := c.Request().Referer()
|
||||||
if referrer == "" {
|
if referrer == "" {
|
||||||
referrer = "/"
|
referrer = "/"
|
||||||
@@ -1055,7 +1057,7 @@ func transcodeToVideoHandler(c echo.Context) error {
|
|||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
log.Errorf("no video record for original %d: %v", originalId, err)
|
log.Errorf("no video record for original %d: %v", originalId, err)
|
||||||
} else {
|
} else {
|
||||||
addVideoTranscode(video.ID, uint(originalId), uint(height))
|
addVideoTranscode(video.ID, uint(originalId), uint(height), fps)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Redirect(http.StatusSeeOther, referrer)
|
return c.Redirect(http.StatusSeeOther, referrer)
|
||||||
|
@@ -25,7 +25,7 @@ type Transcode struct {
|
|||||||
// video fields
|
// video fields
|
||||||
Height uint // target height
|
Height uint // target height
|
||||||
Width uint // target width
|
Width uint // target width
|
||||||
FPS uint // target FPS
|
FPS float64 // target FPS
|
||||||
|
|
||||||
// audio & video fields
|
// audio & video fields
|
||||||
Rate uint
|
Rate uint
|
||||||
|
@@ -55,6 +55,7 @@
|
|||||||
<option value="24">24 fps</option>
|
<option value="24">24 fps</option>
|
||||||
<option value="25">25 fps</option>
|
<option value="25">25 fps</option>
|
||||||
<option value="30">30 fps</option>
|
<option value="30">30 fps</option>
|
||||||
|
<option value="59.94">59.94 fps</option>
|
||||||
<option value="60">60 fps</option>
|
<option value="60">60 fps</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
12
workers.go
12
workers.go
@@ -19,7 +19,7 @@ func ensureDirFor(path string) error {
|
|||||||
return os.MkdirAll(dir, 0700)
|
return os.MkdirAll(dir, 0700)
|
||||||
}
|
}
|
||||||
|
|
||||||
func videoToVideo(transID uint, height uint, srcFilepath string) {
|
func videoToVideo(transID uint, height uint, fps float64, srcFilepath string) {
|
||||||
|
|
||||||
// determine destination path
|
// determine destination path
|
||||||
dstFilename := uuid.Must(uuid.NewV7()).String()
|
dstFilename := uuid.Must(uuid.NewV7()).String()
|
||||||
@@ -47,8 +47,14 @@ func videoToVideo(transID uint, height uint, srcFilepath string) {
|
|||||||
|
|
||||||
// start ffmpeg
|
// start ffmpeg
|
||||||
db.Model(&Transcode{}).Where("id = ?", transID).Update("status", "running")
|
db.Model(&Transcode{}).Where("id = ?", transID).Update("status", "running")
|
||||||
|
var vf string
|
||||||
|
if fps > 0 {
|
||||||
|
vf = fmt.Sprintf("scale=-2:%d,fps=%f", height, fps)
|
||||||
|
} else {
|
||||||
|
vf = fmt.Sprintf("scale=-2:%d", height)
|
||||||
|
}
|
||||||
stdout, stderr, err := ffmpeg.Ffmpeg("-i", srcFilepath,
|
stdout, stderr, err := ffmpeg.Ffmpeg("-i", srcFilepath,
|
||||||
"-vf", fmt.Sprintf("scale=-2:%d", height), "-c:v", "libx264",
|
"-vf", vf, "-c:v", "libx264",
|
||||||
"-crf", "23", "-preset", "veryfast", "-c:a", "aac", "-b:a", fmt.Sprintf("%dk", audioBitrate),
|
"-crf", "23", "-preset", "veryfast", "-c:a", "aac", "-b:a", fmt.Sprintf("%dk", audioBitrate),
|
||||||
dstFilepath)
|
dstFilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -258,7 +264,7 @@ func transcodePending() {
|
|||||||
srcFilepath := filepath.Join(getDataDir(), srcVideo.Filename)
|
srcFilepath := filepath.Join(getDataDir(), srcVideo.Filename)
|
||||||
|
|
||||||
if trans.DstKind == "video" {
|
if trans.DstKind == "video" {
|
||||||
videoToVideo(trans.ID, trans.Height, srcFilepath)
|
videoToVideo(trans.ID, trans.Height, trans.FPS, srcFilepath)
|
||||||
} else if trans.DstKind == "audio" {
|
} else if trans.DstKind == "audio" {
|
||||||
videoToAudio(trans.ID, trans.Rate, srcFilepath)
|
videoToAudio(trans.ID, trans.Rate, srcFilepath)
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user