2020-05-30 04:08:33 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-06-01 23:28:14 +03:00
|
|
|
"log"
|
2020-05-30 04:08:33 +03:00
|
|
|
"os"
|
|
|
|
"os/exec"
|
2020-06-02 02:53:31 +03:00
|
|
|
"path"
|
2020-06-09 11:52:15 +03:00
|
|
|
"strings"
|
2020-05-30 04:08:33 +03:00
|
|
|
)
|
|
|
|
|
2020-06-02 02:53:31 +03:00
|
|
|
func startFfmpeg(configuration Config) {
|
|
|
|
var outputDir = configuration.PublicHLSPath
|
2020-06-09 11:52:15 +03:00
|
|
|
var variantPlaylistPath = configuration.PublicHLSPath
|
2020-05-30 04:08:33 +03:00
|
|
|
|
2020-06-03 11:34:05 +03:00
|
|
|
if configuration.IPFS.Enabled || configuration.S3.Enabled {
|
2020-06-02 02:53:31 +03:00
|
|
|
outputDir = configuration.PrivateHLSPath
|
2020-06-09 11:52:15 +03:00
|
|
|
variantPlaylistPath = configuration.PrivateHLSPath
|
2020-06-02 02:53:31 +03:00
|
|
|
}
|
2020-06-01 23:28:14 +03:00
|
|
|
|
2020-06-09 11:52:15 +03:00
|
|
|
outputDir = path.Join(outputDir, "%v")
|
|
|
|
|
|
|
|
// var masterPlaylistName = path.Join(configuration.PublicHLSPath, "%v", "stream.m3u8")
|
|
|
|
var variantPlaylistName = path.Join(variantPlaylistPath, "%v", "stream.m3u8")
|
|
|
|
// var variantRootPath = configuration.PublicHLSPath
|
|
|
|
|
|
|
|
// variantRootPath = path.Join(variantRootPath, "%v")
|
|
|
|
// variantPlaylistName := path.Join("%v", "stream.m3u8")
|
|
|
|
|
|
|
|
log.Printf("Starting transcoder saving to /%s.", variantPlaylistName)
|
2020-06-02 03:42:36 +03:00
|
|
|
pipePath := getTempPipePath()
|
2020-06-01 23:28:14 +03:00
|
|
|
|
2020-06-09 11:52:15 +03:00
|
|
|
var videoMaps = make([]string, 0)
|
|
|
|
var streamMaps = make([]string, 0)
|
|
|
|
var audioMaps = make([]string, 0)
|
|
|
|
for index, quality := range configuration.VideoSettings.StreamQualities {
|
|
|
|
videoMaps = append(videoMaps, fmt.Sprintf("-map v:0 -c:v:%d libx264 -b:v:%d %s", index, index, quality.Bitrate))
|
|
|
|
streamMaps = append(streamMaps, fmt.Sprintf("v:%d,a:%d", index, index))
|
|
|
|
audioMaps = append(audioMaps, "-map a:0")
|
|
|
|
}
|
|
|
|
|
|
|
|
ffmpegFlags := []string{
|
|
|
|
"-hide_banner",
|
|
|
|
"-i pipe:",
|
2020-06-10 09:35:40 +03:00
|
|
|
"-vf scale=900:-2",
|
|
|
|
"-sws_flags fast_bilinear",
|
|
|
|
strings.Join(videoMaps, " "), // All the different video variants
|
2020-06-09 12:47:02 +03:00
|
|
|
strings.Join(audioMaps, " ") + " -c:a copy", // Audio for all the variants
|
|
|
|
// strings.Join(audioMaps, " ") + " -c:a aac -b:a 192k -ac 2", // Audio for all the variants
|
2020-06-09 11:52:15 +03:00
|
|
|
"-master_pl_name stream.m3u8",
|
|
|
|
"-g 48",
|
|
|
|
"-keyint_min 48",
|
2020-06-09 23:15:44 +03:00
|
|
|
"-preset " + configuration.VideoSettings.EncoderPreset,
|
2020-06-09 11:52:15 +03:00
|
|
|
"-sc_threshold 0",
|
|
|
|
"-profile:v high",
|
|
|
|
"-f hls",
|
|
|
|
"-hls_list_size 30",
|
|
|
|
"-hls_time 10",
|
|
|
|
"-strftime 1",
|
|
|
|
"-use_localtime 1",
|
|
|
|
"-hls_playlist_type event",
|
|
|
|
"-hls_segment_filename " + path.Join(outputDir, "stream-%Y%m%d-%s.ts"),
|
|
|
|
"-hls_flags delete_segments+program_date_time+temp_file",
|
|
|
|
"-segment_wrap 100",
|
2020-06-09 12:56:23 +03:00
|
|
|
"-tune zerolatency",
|
|
|
|
|
2020-06-09 12:47:02 +03:00
|
|
|
// "-master_m3u8_publish_rate 5",
|
2020-06-09 11:52:15 +03:00
|
|
|
"-var_stream_map \"" + strings.Join(streamMaps, " ") + "\"",
|
|
|
|
variantPlaylistName,
|
|
|
|
}
|
|
|
|
|
|
|
|
ffmpegFlagsString := strings.Join(ffmpegFlags, " ")
|
|
|
|
|
|
|
|
ffmpegCmd := "cat " + pipePath + " | " + configuration.FFMpegPath + " " + ffmpegFlagsString
|
|
|
|
|
|
|
|
// fmt.Println(ffmpegCmd)
|
2020-06-01 23:28:14 +03:00
|
|
|
|
2020-06-10 04:28:07 +03:00
|
|
|
_, err := exec.Command("sh", "-c", ffmpegCmd).Output()
|
2020-06-09 11:52:15 +03:00
|
|
|
fmt.Println(err)
|
2020-05-30 04:08:33 +03:00
|
|
|
verifyError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func writePlaylist(data string, filePath string) {
|
|
|
|
f, err := os.Create(filePath)
|
2020-06-01 22:15:07 +03:00
|
|
|
defer f.Close()
|
|
|
|
|
2020-05-30 04:08:33 +03:00
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
_, err = f.WriteString(data)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|