m3u8格式转成MP4-使用go语言实现
在此写m3u8转mp4代码
原理就是,按照m3u8文件的顺序,合并若干个小的ts文件,写入总mp4。
代码中的网址已删。
/*
最终版
*/
package main
import (
"fmt"
"net/http"
"io/ioutil"
"sync"
"time"
"os"
"log"
"regexp"
)
var file *os.File
var wg sync.WaitGroup
var host string = "vom"
var date string = "20201221"
var str string = "8btdG2by"
var flag string = "500kb"
var cate string = "putong"
var origin string = "http://www.com"
var g_referer string = "http://www..com/player.html"
func main() {
logFile, _ := os.OpenFile("log.log", os.O_CREATE|os.O_APPEND, 0766)
log.SetOutput(logFile)
url := fmt.Sprintf("https://%s/%s/%s/%s/%s/hls/index.m3u8", host, cate, date, str, flag)
err := GetM3u8(url)
if err != nil {
fmt.Printf("Get_m3u8 err")
return
}
num := RegexpUrl(url); if num == 0 {
return
}
wg.Wait()
fmt.Println("all done")
}
//正则匹配
func RegexpUrl(url string) int{
b, err := ioutil.ReadFile("1.txt")
if err != nil{
fmt.Println(err)
return 0
}
reg := "[0-9a-zA-Z]{8,}.ts"
compile := regexp.MustCompile(reg)
html := []byte(string(b))
submatch := compile.FindAllSubmatch(html, -1)
num := len(submatch)
if num == 0 {
fmt.Println("no match")
return 0
}
log.Printf("%s %d\n", url, num)
for k, v := range submatch{
//https://video.huishenghuo888888.com:8091/jingpin/20201224/Lb21hJIr/500kb/hls/oKm4ssYj.ts
url := fmt.Sprintf("https://%s/%s/%s/%s/%s/hls/%s", host, cate, date, str, flag, string(v[0]))
fmt.Printf("go %d %s\n", k, url)
wg.Add(1)
go GetTs(url, k)
if k % 50 == 0 {
time.Sleep(time.Second * 2)
}
}
return num
}
func GetM3u8(url string) error{
client := &http.Client{}
req,_ := http.NewRequest("GET",url,nil)
req.Header.Add("Origin", origin)
req.Header.Add("Referer", g_referer)
req.Header.Add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0")
req.Header.Add("Connection", "Close")
response, err := client.Do(req)
if err != nil {
fmt.Println("http get error ",err)
for {
fmt.Println("retry", url)
response, err = client.Do(req)
if err == nil {
break
}
}
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println("ioutil.ReadAll(response.Body) ",err)
return err
}
//img := strings.Replace(url, "/", "_", -1)
filename := "1.txt"
err = ioutil.WriteFile(filename, body, 0666)
if err != nil {
fmt.Println("ioutil.WriteFile error", err)
return err
}
fmt.Println(url, " ok")
return nil
}
func GetTs(url string, k int) {
defer wg.Done()
filename := fmt.Sprintf("./ts/%d.ts", k)
file,err := os.Open(filename)
if err == nil{
fmt.Println(k, " exist")
file.Close()
return
}
client := &http.Client{}
req,_ := http.NewRequest("GET",url,nil)
req.Header.Add("Origin", origin)
req.Header.Add("Referer", g_referer)
req.Header.Add("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66")
response, err := client.Do(req)
if err != nil {
for {
fmt.Println("retry", url)
response, err = client.Do(req)
if err == nil {
break
}
}
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
for {
fmt.Println("retry ReadBody", url)
response, err = client.Do(req)
if err == nil {
body, err = ioutil.ReadAll(response.Body)
if err == nil {
break
}
}
}
}
err = ioutil.WriteFile(filename, body, 0666)
if err != nil {
fmt.Println("ioutil.WriteFile error", err)
return
}
fmt.Println(url, k, " ok")
}
func MergeTs(num int, id int, str string) {
tsFile := fmt.Sprintf("./merge/all_%d_%s.ts", id, str)
fii, err := os.OpenFile(tsFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
defer fii.Close()
for i := 0; i < num; i++ {
ts_file := fmt.Sprintf("./output/%d_out.ts", i)
f, err := os.OpenFile(ts_file, os.O_RDONLY, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
b, err := ioutil.ReadAll(f)
if err != nil {
fmt.Println(err)
return
}
//追加写入
fii.Write(b)
f.Close()
//删除文件
os.Remove(ts_file)
fmt.Println(i, "ok")
}
fmt.Println("done")
}
/*
*/
package main
import (
"fmt"
"net/http"
"io/ioutil"
"sync"
"strconv"
"time"
"os"
"regexp"
)
var file *os.File
var wg sync.WaitGroup
var date int
var str string
func main() {
date = 1229
str = "1229"
url := "https://c----------t.m3u8"
err := Get_m3u8(url)
if err != nil {
fmt.Printf("Get_m3u8 err")
return
}
file, _ = os.OpenFile("err.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)//
defer file.Close()
b, err := ioutil.ReadFile("1.txt")
if err != nil{
fmt.Println(err)
}
reg := "[a-z0-9]{6}.ts"
compile := regexp.MustCompile(reg)
html := []byte(string(b))
submatch := compile.FindAllSubmatch(html, -1)
if len(submatch) == 0 {
fmt.Println("no match")
return
}
num := len(submatch)
file.WriteString(fmt.Sprintf("\n\ndown %s num=%d\n", url, num))
wg.Add(num)
for k, v := range submatch{
url := "https://c----4/" + string(v[0])
fmt.Printf("go %s\n", url)
go Get_Save_ts(url, k)
if k % 20 == 0 {
time.Sleep(time.Second * 2)
}
}
fmt.Println(num)
wg.Wait()
var i int
for i=0; i < num; i++ {
filename := fmt.Sprintf("./ts/%d.ts", i)
file,err := os.Open(filename)
if err != nil{
break
}
file.Close()
}
if i != num {
fmt.Println("not all")
return
}
Merge_m3u8(num, date, str)
}
func Get_m3u8(url string) error{
client := &http.Client{}
req,_ := http.NewRequest("GET",url,nil)
//referer := fmt.Sprintf("https://---.com/%d/%s/index.m3u8", date, str)
//req.Header.Add("Referer", referer)
req.Header.Add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0")
req.Header.Add("Connection", "Close")
response, err := client.Do(req)
if err != nil {
fmt.Println("http get error ",err)
//return
for {
fmt.Println("retry", url)
response, err = client.Do(req)
if err == nil {
break
}
}
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println("ioutil.ReadAll(response.Body) ",err)
return err
}
filename := "1.txt"
err = ioutil.WriteFile(filename, body, 0666)
if err != nil {
fmt.Println("ioutil.WriteFile error", err)
return err
}else {
fmt.Println(url, " ok")
}
return nil
}
func Get_Save_ts(url string, k int) {
defer wg.Done()
client := &http.Client{}
req,_ := http.NewRequest("GET",url,nil)
req.Header.Add("origin", "https://www.-.com")
req.Header.Add("referer", "https://www.--com/video/video_play.html?video_id=20807")
req.Header.Add("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66")
//req.Header.Add("Connection", "Close")
response, err := client.Do(req)
if err != nil {
fmt.Println("client.Do",err)
file.WriteString(strconv.Itoa(int(k)) + url)
file.WriteString("\n")
//return
for {
fmt.Println("retry", url)
response, err = client.Do(req)
if err == nil {
break
}
}
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println(url, "ioutil.ReadAll(response.Body) ",err)
file.WriteString(strconv.Itoa(int(k)) + url)
file.WriteString("\n")
//return
for {
fmt.Println("retry ReadBody", url)
response, err = client.Do(req)
if err == nil {
body, err = ioutil.ReadAll(response.Body)
if err == nil {
break
}
}
}
}
filename := fmt.Sprintf("./ts/%d.ts", k)
file,err := os.Open(filename)
if err == nil{ //已经存在文件,return
fmt.Println(k, " exist")
file.Close()
return
}
err = ioutil.WriteFile(filename, body, 0666)
if err != nil {
fmt.Println("ioutil.WriteFile error", err)
return
}else {
fmt.Println(url, k, " ok")
}
}
func Merge_m3u8(num int, ts_id int, str string) {
tsFile := fmt.Sprintf("./merge/all_%d_%s.ts", ts_id, str)
fii, err := os.OpenFile(tsFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
defer fii.Close()
for i := 0; i < num; i++ {
ts_file := fmt.Sprintf("./ts/%d.ts", i)
f, err := os.OpenFile(ts_file, os.O_RDONLY, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
b, err := ioutil.ReadAll(f)
if err != nil {
fmt.Println(err)
return
}
fii.Write(b)
f.Close()
os.Remove(ts_file)
fmt.Println(i, "ok")
}
fmt.Println("done")
}
参考
https://studygolang.com/articles/2687
本文介绍了如何使用Go语言将m3u8格式的视频流合并成MP4文件,主要原理是按照m3u8清单的顺序,将多个ts段合并到一个MP4文件中。
8377

被折叠的 条评论
为什么被折叠?



