Add transcode handlers
This commit is contained in:
202
handlers.go
202
handlers.go
@@ -311,7 +311,6 @@ func getVideoFPS(path string) (float64, error) {
|
|||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this produces a string like "num/denom", do the division
|
|
||||||
parts := strings.Split(strings.TrimSpace(stdout.String()), "/")
|
parts := strings.Split(strings.TrimSpace(stdout.String()), "/")
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
fmt.Println("getVideoFPS split error:", err, stdout.String())
|
fmt.Println("getVideoFPS split error:", err, stdout.String())
|
||||||
@@ -371,10 +370,13 @@ type VideoMeta struct {
|
|||||||
height uint
|
height uint
|
||||||
fps float64
|
fps float64
|
||||||
length float64
|
length float64
|
||||||
|
size int64 // file size
|
||||||
}
|
}
|
||||||
|
|
||||||
type AudioMeta struct {
|
type AudioMeta struct {
|
||||||
rate uint
|
rate uint
|
||||||
|
length float64
|
||||||
|
size int64 // file size
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVideoMeta(path string) (VideoMeta, error) {
|
func getVideoMeta(path string) (VideoMeta, error) {
|
||||||
@@ -394,11 +396,16 @@ func getVideoMeta(path string) (VideoMeta, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return VideoMeta{}, err
|
return VideoMeta{}, err
|
||||||
}
|
}
|
||||||
|
size, err := getSize(path)
|
||||||
|
if err != nil {
|
||||||
|
return VideoMeta{}, err
|
||||||
|
}
|
||||||
return VideoMeta{
|
return VideoMeta{
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
fps: fps,
|
fps: fps,
|
||||||
length: length,
|
length: length,
|
||||||
|
size: size,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,11 +447,47 @@ func getAudioMeta(path string) (AudioMeta, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return AudioMeta{}, err
|
return AudioMeta{}, err
|
||||||
}
|
}
|
||||||
|
length, err := getLength(path)
|
||||||
|
if err != nil {
|
||||||
|
return AudioMeta{}, err
|
||||||
|
}
|
||||||
|
size, err := getSize(path)
|
||||||
|
if err != nil {
|
||||||
|
return AudioMeta{}, err
|
||||||
|
}
|
||||||
return AudioMeta{
|
return AudioMeta{
|
||||||
rate: rate,
|
rate: rate,
|
||||||
|
length: length,
|
||||||
|
size: size,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addAudioTranscode(mediaId, originalId, bitrate uint, srcKind string) {
|
||||||
|
t := Transcode{
|
||||||
|
SrcID: mediaId,
|
||||||
|
OriginalID: originalId,
|
||||||
|
SrcKind: srcKind,
|
||||||
|
DstKind: "audio",
|
||||||
|
Rate: bitrate,
|
||||||
|
TimeSubmit: time.Now(),
|
||||||
|
Status: "pending",
|
||||||
|
}
|
||||||
|
db.Create(&t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addVideoTranscode(videoId, originalId, targetHeight uint) {
|
||||||
|
t := Transcode{
|
||||||
|
SrcID: videoId,
|
||||||
|
OriginalID: originalId,
|
||||||
|
SrcKind: "video",
|
||||||
|
DstKind: "video",
|
||||||
|
Height: targetHeight,
|
||||||
|
TimeSubmit: time.Now(),
|
||||||
|
Status: "pending",
|
||||||
|
}
|
||||||
|
db.Create(&t)
|
||||||
|
}
|
||||||
|
|
||||||
func processOriginal(originalID uint) {
|
func processOriginal(originalID uint) {
|
||||||
|
|
||||||
// check if there is an original video
|
// check if there is an original video
|
||||||
@@ -469,54 +512,16 @@ func processOriginal(originalID uint) {
|
|||||||
fmt.Println("Skipping non-existant file for processOriginal")
|
fmt.Println("Skipping non-existant file for processOriginal")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
videoMeta, err := getVideoMeta(videoFilepath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println(videoMeta)
|
|
||||||
db.Model(&Video{}).Where("id = ?", video.ID).Update("fps", videoMeta.fps)
|
|
||||||
db.Model(&Video{}).Where("id = ?", video.ID).Update("width", videoMeta.width)
|
|
||||||
db.Model(&Video{}).Where("id = ?", video.ID).Update("height", videoMeta.height)
|
|
||||||
db.Model(&Video{}).Where("id = ?", video.ID).Updates(map[string]interface{}{
|
|
||||||
"fps": videoMeta.fps,
|
|
||||||
"width": videoMeta.width,
|
|
||||||
"height": videoMeta.height,
|
|
||||||
"length": videoMeta.length,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
videoSize, err := getSize(videoFilepath)
|
|
||||||
if err == nil {
|
|
||||||
db.Model(&Video{}).Where("id = ?", video.ID).Update("size", videoSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create audio transcodes
|
// create audio transcodes
|
||||||
for _, bitrate := range []uint{64, 96, 128, 160, 192} {
|
for _, bitrate := range []uint{64, 96, 128, 160, 192} {
|
||||||
t := Transcode{
|
addAudioTranscode(video.ID, originalID, bitrate, "video")
|
||||||
SrcID: video.ID,
|
|
||||||
OriginalID: originalID,
|
|
||||||
SrcKind: "video",
|
|
||||||
DstKind: "audio",
|
|
||||||
Rate: bitrate,
|
|
||||||
TimeSubmit: time.Now(),
|
|
||||||
Status: "pending",
|
|
||||||
}
|
|
||||||
db.Create(&t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create video transcodes
|
// create video transcodes
|
||||||
for _, targetHeight := range []uint{144, 480, 720, 1080} {
|
for _, targetHeight := range []uint{144, 480, 720, 1080} {
|
||||||
if targetHeight <= videoMeta.height {
|
if targetHeight <= video.Height {
|
||||||
t := Transcode{
|
addVideoTranscode(video.ID, originalID, targetHeight)
|
||||||
SrcID: video.ID,
|
|
||||||
OriginalID: originalID,
|
|
||||||
SrcKind: "video",
|
|
||||||
DstKind: "video",
|
|
||||||
Height: targetHeight,
|
|
||||||
TimeSubmit: time.Now(),
|
|
||||||
Status: "pending",
|
|
||||||
}
|
|
||||||
db.Create(&t)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,35 +533,14 @@ func processOriginal(originalID uint) {
|
|||||||
fmt.Println("Skipping non-existant audio file for processOriginal")
|
fmt.Println("Skipping non-existant audio file for processOriginal")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
audioMeta, err := getAudioMeta(audioFilepath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println(audioMeta)
|
|
||||||
db.Model(&Audio{}).Where("id = ?", audio.ID).Update("bps", audioMeta.rate)
|
|
||||||
}
|
|
||||||
|
|
||||||
size, err := getSize(audioFilepath)
|
|
||||||
if err == nil {
|
|
||||||
db.Model(&Audio{}).Where("id = ?", audio.ID).Update("size", size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create audio transcodes
|
// create audio transcodes
|
||||||
for _, bitrate := range []uint{64, 96, 128, 160, 192} {
|
for _, bitrate := range []uint{64, 96, 128, 160, 192} {
|
||||||
t := Transcode{
|
addAudioTranscode(video.ID, originalID, bitrate, "audio")
|
||||||
SrcID: audio.ID,
|
|
||||||
OriginalID: originalID,
|
|
||||||
SrcKind: "audio",
|
|
||||||
DstKind: "audio",
|
|
||||||
Rate: bitrate,
|
|
||||||
TimeSubmit: time.Now(),
|
|
||||||
Status: "pending",
|
|
||||||
}
|
|
||||||
db.Create(&t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("No original video or audio for %d found in processOriginal", originalID)
|
log.Errorf("No original video or audio for original %d found in processOriginal", originalID)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -610,17 +594,21 @@ func startDownload(originalID uint, videoURL string, audioOnly bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
length, _ := getLength(dlFilepath)
|
|
||||||
size, _ := getSize(dlFilepath)
|
|
||||||
|
|
||||||
if audioOnly {
|
if audioOnly {
|
||||||
|
mediaMeta, err := getAudioMeta(dlFilepath)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("couldn't get audio file metadata", err)
|
||||||
|
SetOriginalStatus(originalID, Failed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
audio := Audio{
|
audio := Audio{
|
||||||
OriginalID: originalID,
|
OriginalID: originalID,
|
||||||
Filename: dlFilename,
|
Filename: dlFilename,
|
||||||
Source: "original",
|
Source: "original",
|
||||||
Type: origMeta.ext,
|
Type: origMeta.ext,
|
||||||
Length: length,
|
Length: mediaMeta.length,
|
||||||
Size: size,
|
Size: mediaMeta.size,
|
||||||
}
|
}
|
||||||
fmt.Println("create Audio", audio)
|
fmt.Println("create Audio", audio)
|
||||||
if db.Create(&audio).Error != nil {
|
if db.Create(&audio).Error != nil {
|
||||||
@@ -629,17 +617,27 @@ func startDownload(originalID uint, videoURL string, audioOnly bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
mediaMeta, err := getVideoMeta(dlFilepath)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("couldn't get video file metadata", err)
|
||||||
|
SetOriginalStatus(originalID, Failed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
video := Video{
|
video := Video{
|
||||||
OriginalID: originalID,
|
OriginalID: originalID,
|
||||||
Filename: dlFilename,
|
Filename: dlFilename,
|
||||||
Source: "original",
|
Source: "original",
|
||||||
Type: origMeta.ext,
|
Type: origMeta.ext,
|
||||||
Length: length,
|
FPS: mediaMeta.fps,
|
||||||
Size: size,
|
Width: mediaMeta.width,
|
||||||
|
Height: mediaMeta.height,
|
||||||
|
Length: mediaMeta.length,
|
||||||
|
Size: mediaMeta.size,
|
||||||
}
|
}
|
||||||
fmt.Println("create Video", video)
|
log.Debugln("create Video", video)
|
||||||
if db.Create(&video).Error != nil {
|
if db.Create(&video).Error != nil {
|
||||||
fmt.Println("Couldn't create video entry", err)
|
log.Errorln("Couldn't create video entry", err)
|
||||||
SetOriginalStatus(originalID, Failed)
|
SetOriginalStatus(originalID, Failed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -927,6 +925,58 @@ func deleteAudioHandler(c echo.Context) error {
|
|||||||
return c.Redirect(http.StatusSeeOther, referrer)
|
return c.Redirect(http.StatusSeeOther, referrer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func transcodeToVideoHandler(c echo.Context) error {
|
||||||
|
originalId, _ := strconv.ParseUint(c.FormValue("original_id"), 10, 32)
|
||||||
|
height, _ := strconv.ParseUint(c.FormValue("height"), 10, 32)
|
||||||
|
referrer := c.Request().Referer()
|
||||||
|
if referrer == "" {
|
||||||
|
referrer = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
var video Video
|
||||||
|
err := db.Where("source = ?", "original").Where("original_id = ?", originalId).First(&video).Error
|
||||||
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
log.Errorf("no video record for original %d: %v", originalId, err)
|
||||||
|
} else {
|
||||||
|
addVideoTranscode(video.ID, uint(originalId), uint(height))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Redirect(http.StatusSeeOther, referrer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func transcodeToAudioHandler(c echo.Context) error {
|
||||||
|
originalId, _ := strconv.ParseUint(c.FormValue("original_id"), 10, 32)
|
||||||
|
kbps, _ := strconv.ParseUint(c.FormValue("kbps"), 10, 32)
|
||||||
|
referrer := c.Request().Referer()
|
||||||
|
if referrer == "" {
|
||||||
|
referrer = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if there is an original video
|
||||||
|
hasOriginalVideo := true
|
||||||
|
hasOriginalAudio := true
|
||||||
|
var video Video
|
||||||
|
var audio Audio
|
||||||
|
err := db.Where("source = ?", "original").Where("original_id = ?", originalId).First(&video).Error
|
||||||
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
hasOriginalVideo = false
|
||||||
|
}
|
||||||
|
err = db.Where("source = ?", "original").Where("original_id = ?", originalId).First(&audio).Error
|
||||||
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
hasOriginalAudio = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasOriginalVideo {
|
||||||
|
addAudioTranscode(video.ID, uint(originalId), uint(kbps), "video")
|
||||||
|
} else if hasOriginalAudio {
|
||||||
|
addAudioTranscode(audio.ID, uint(originalId), uint(kbps), "audio")
|
||||||
|
} else {
|
||||||
|
log.Errorln("no audio or video record for original", originalId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Redirect(http.StatusSeeOther, referrer)
|
||||||
|
}
|
||||||
|
|
||||||
func tempHandler(c echo.Context) error {
|
func tempHandler(c echo.Context) error {
|
||||||
token := c.Param("token")
|
token := c.Param("token")
|
||||||
|
|
||||||
|
2
main.go
2
main.go
@@ -125,6 +125,8 @@ func main() {
|
|||||||
e.POST("/video/:id/process", processHandler, authMiddleware)
|
e.POST("/video/:id/process", processHandler, authMiddleware)
|
||||||
e.POST("/delete_video/:id", deleteVideoHandler, authMiddleware)
|
e.POST("/delete_video/:id", deleteVideoHandler, authMiddleware)
|
||||||
e.POST("/delete_audio/:id", deleteAudioHandler, authMiddleware)
|
e.POST("/delete_audio/:id", deleteAudioHandler, authMiddleware)
|
||||||
|
e.POST("/transcode_to_video/:id", transcodeToVideoHandler, authMiddleware)
|
||||||
|
e.POST("/transcode_to_audio/:id", transcodeToAudioHandler, authMiddleware)
|
||||||
|
|
||||||
dataGroup := e.Group("/data")
|
dataGroup := e.Group("/data")
|
||||||
dataGroup.Use(authMiddleware)
|
dataGroup.Use(authMiddleware)
|
||||||
|
@@ -36,6 +36,19 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<div class="media-card">
|
||||||
|
<form action="/transcode_to_video/{{.original.ID}}" method="post">
|
||||||
|
<input type="hidden" name="original_id" value="{{.original.ID}}">
|
||||||
|
<label for="height-select">Height:</label>
|
||||||
|
<select name="height" id="height-select">
|
||||||
|
<option value="144">144p</option>
|
||||||
|
<option value="240">240p</option>
|
||||||
|
<option value="360">360p</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button type="submit">Transcode</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-grid">
|
<div class="media-grid">
|
||||||
{{range .audios}}
|
{{range .audios}}
|
||||||
@@ -59,6 +72,18 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<div class="media-card">
|
||||||
|
<form action="/transcode_to_audio/{{.original.ID}}" method="post">
|
||||||
|
<input type="hidden" name="original_id" value="{{.original.ID}}">
|
||||||
|
<label for="kbps-select">Kbps:</label>
|
||||||
|
<select name="kbps" id="kbps-select">
|
||||||
|
<option value="64">64 kbps</option>
|
||||||
|
<option value="96">96 kbps</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button type="submit">Transcode</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user