134 lines
2.9 KiB
Go
134 lines
2.9 KiB
Go
|
package hls
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"openmediacenter/apiGo/config"
|
||
|
"openmediacenter/apiGo/database"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type TranscodingState struct {
|
||
|
Finished bool
|
||
|
Active bool
|
||
|
}
|
||
|
|
||
|
var transcodeAcive = make(map[uint32]TranscodingState)
|
||
|
|
||
|
func startSegmentation(videoid uint32) {
|
||
|
transcodeAcive[videoid] = TranscodingState{
|
||
|
Finished: false,
|
||
|
Active: true,
|
||
|
}
|
||
|
|
||
|
cfg := config.GetConfig()
|
||
|
outpath := fmt.Sprintf("%s/%d", cfg.General.TmpDir, videoid)
|
||
|
|
||
|
if !fileExists(outpath) {
|
||
|
err := os.MkdirAll(outpath, os.ModePerm)
|
||
|
if err != nil {
|
||
|
log.Println(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
app := "ffmpeg"
|
||
|
inputpath := GetVideoPathById(videoid)
|
||
|
fmt.Println(inputpath)
|
||
|
cmd := exec.Command(app,
|
||
|
//"-hide_banner",
|
||
|
//"-loglevel", "panic",
|
||
|
"-n",
|
||
|
//"-t", "10.0",
|
||
|
//"-ss", fmt.Sprintf("%d", id*10),
|
||
|
"-i", inputpath,
|
||
|
//"-g", "52",
|
||
|
//"-sc_threshold", "0",
|
||
|
//"-force_key_frames", "expr:gte(t,n_forced*10)",
|
||
|
//"-strict", "experimental",
|
||
|
//"-movflags", "+frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov",
|
||
|
//"-c:v", "libx264",
|
||
|
//"-crf", "18",
|
||
|
//
|
||
|
//"-f", "segment",
|
||
|
//"-segment_time_delta", "0.2",
|
||
|
//"-segment_format", "mpegts",
|
||
|
//"-segment_times", commaSeparatedTimes,
|
||
|
//"-segment_start_number", `0`,
|
||
|
//"-segment_list_type", "flat",
|
||
|
//"-segment_list",
|
||
|
"-preset", "veryfast",
|
||
|
//"-maxrate", "4000k",
|
||
|
//"-bufsize", "8000k",
|
||
|
//"-vf", "scale=1280:-1,format=yuv420p",
|
||
|
//"-c:a", "aac",
|
||
|
"-force_key_frames", "expr:gte(t,n_forced*10)",
|
||
|
"-strict", "-2",
|
||
|
"-c:a", "aac",
|
||
|
"-c:v", "libx264",
|
||
|
"-f", "segment",
|
||
|
"-segment_list_type", "m3u8",
|
||
|
"-segment_time", "10.0",
|
||
|
"-segment_time_delta", "0.001",
|
||
|
"-segment_list", "test.m3u8", outpath+"/part%02d.ts")
|
||
|
|
||
|
stdout, err := cmd.Output()
|
||
|
//
|
||
|
if err != nil {
|
||
|
fmt.Println(err.Error())
|
||
|
fmt.Println(string(err.(*exec.ExitError).Stderr))
|
||
|
}
|
||
|
fmt.Println(stdout)
|
||
|
fmt.Println("finished transcoding")
|
||
|
|
||
|
transcodeAcive[videoid] = TranscodingState{
|
||
|
Finished: true,
|
||
|
Active: false,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func fileExists(path string) bool {
|
||
|
_, err := os.Stat(path)
|
||
|
return !os.IsNotExist(err)
|
||
|
}
|
||
|
|
||
|
func GetVideoPathById(videoid uint32) string {
|
||
|
query := fmt.Sprintf(`SELECT movie_url FROM videos WHERE movie_id=%d`, videoid)
|
||
|
var url string
|
||
|
|
||
|
err := database.QueryRow(query).Scan(&url)
|
||
|
if err != nil {
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
mSettings, _, _ := database.GetSettings()
|
||
|
vidFolder := config.GetConfig().General.ReindexPrefix + mSettings.VideoPath
|
||
|
return vidFolder + url
|
||
|
}
|
||
|
|
||
|
func GetSegment(segIdx uint32, videoid uint32) string {
|
||
|
cfg := config.GetConfig()
|
||
|
|
||
|
i, ok := transcodeAcive[videoid]
|
||
|
if ok {
|
||
|
if !i.Active && !i.Finished {
|
||
|
go startSegmentation(videoid)
|
||
|
}
|
||
|
} else {
|
||
|
go startSegmentation(videoid)
|
||
|
}
|
||
|
|
||
|
// todo timeout
|
||
|
tspath := fmt.Sprintf("%s/%d/part%02d.ts", cfg.General.TmpDir, videoid, segIdx)
|
||
|
if ok && i.Finished == true {
|
||
|
return tspath
|
||
|
}
|
||
|
|
||
|
fmt.Println("checking if part exists")
|
||
|
for !fileExists(fmt.Sprintf("%s/%d/part%02d.ts", cfg.General.TmpDir, videoid, segIdx+1)) {
|
||
|
time.Sleep(100 * time.Millisecond)
|
||
|
}
|
||
|
return tspath
|
||
|
}
|