m3u8d

package module
v1.24.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 11, 2024 License: MIT Imports: 30 Imported by: 0

README

m3u8视频下载工具

  • 没有ffmpeg依赖, 不需要单独配置任何环境
  • 提供windows图形界面(Qt), mac、linux命令行, linux支持arm、386、mipsle
  • 程序会自动将下载的ts文件合并转换格式为mp4
  • 全部版本下载, 包括windows图形界面/linux命令行/mac命令行/mac图形化界面
  • 命令行使用教程
    • 普通下载命令: ./m3u8d download -u https://example.com/index.m3u8
    • curl模式: ./m3u8d curl 'https://example.com/index.m3u8' -H 'cookie: CONSENT=YES'
    • 合并某个目录下的ts文件为 mp4: ./m3u8d merge --InputTsDir /root/save --OutputMp4Name save.mp4

实现说明

  • download.go 大部分抄自 llychao/m3u8-downloader
  • 使用gomedia 代替ffmpeg进行格式转换
  • 支持跳过前面几个ts文件(一般是广告, 嘿嘿)
  • 支持跳过 #EXT-X-DISCONTINUITY 标签包裹的ts。有的网站会在视频中增加广告,广告内容在 #EXT-X-DISCONTINUITY 直接包裹
  • 程序会在下载保存目录创建:
    • downloading/ 目录, 用于存放正在下载的分段ts视频, 按照m3u8的url进行划分
    • m3u8d_config.json 文件, 用于存放Qt ui的的界面上的配置信息, 只有Windows/Macos的Qt版本会创建此文件
  • curl模式 可以赋予使用者任意设置下载请求的Header信息的能力,方便解决只有一个m3u8的链接时无法下载视频的尴尬局面
    • 例子1, 你需要下载的视频是要登陆后观看的,Cookie信息里存放了登陆状态
    • 例子2, 网站开发者验证了Referer信息、Authority信息、Origin信息、User-Agent信息、各种特定的Header信息
    • 以windows下的chrome为例,找到对应的m3u8请求记录,然后右键选择 "Copy - Copy as cURL(bash)", 然后打开 windows-qt版本的 m3u8d, 点击 "curl 模式",将复制出来的请求粘贴上去即可
  • 已有功能列表
    • 如果不是m3u8样子的URL,自动下载html下来、搜索其中的m3u8链接进行下载
    • windows、linux、mac都支持转换、合并ts格式为mp4
    • 充分测试后,使用 gomedia 代替ffmpeg进行格式转换
    • 支持嵌套m3u8的url
    • 增加openwrt路由器的mipsle二进制
    • 支持从curl命令解析出需要的信息,正如 cxjava/m3u8-downloader 一样
    • 显示下载速度、合并ts的速度
    • 提供macos的图形化界面
    • 支持下载aes加密的m3u8
    • 内部使用多线程下载ts文件
    • 支持设置代理: http/socks5
      • http代理解释: 要访问的真实url是http协议, 使用代理服务器可见的GET/POST/HEAD...形式; 如果要访问的真实url是https协议, 使用代理服务器不可见的CONNECT形式

TODO:

  • 多线程修改为自适应模式,在下载过程中动态调整线程池大小,以便达到最快的下载速度
  • 支持多国语言
  • 支持从一个txt里读取下载列表,批量下载

二次开发操作手册:

  • 如果只开发命令行版本, 则只需要修改*.go文件, 然后编译 cmd/main.go 即可
  • 如果涉及到Qt界面打包, 则需要运行 export/main.go 将 *.go导出为Qt界面需要的 m3u8-qt/m3u8.h,m3u8-qt/m3u8.cpp, m3u8-qt/m3u8-impl.a. 然后使用QtCreator进行打包

发布协议

开发支持


关于为什么使用 gomedia 替代 ffmpeg

引入ffmpeg很麻烦, 原因列表:

  1. ffmpeg开源协议是 GPL的,具有传染性, 这个项目的主要逻辑就不能使用 MIT 开源了
  2. 如果使用cgo调用的形式引入ffmpeg
    • 最终二进制体积特别大
    • 编译mac/linux/路由器 版本的时候必然要依赖对应的跨平台编译器, 编译难度提升
  3. 如果使用内嵌 静态编译的ffmpeg二进制, 使用的时候释放到 临时目录再调用命令行
    • 最终二进制体积会更大, 可以看以前的v1.1版本 , 每个最终二进制都比现在大25MB左右
    • 没找到mipsle路由器版本的静态编译的ffmpeg
  4. 如果直接调用ffmpeg命令, 用户则必须首先安装ffmpeg到操作系统, 难用

引入MIT协议的gomedia解决ts转换成mp4好处

  1. gomedia是纯go代码, 跨平台编译容易
  2. 本项目也可以使用MIT协议进行开源, 无需限定为GPL/LGPL
  3. 最终二进制体积特别小, linux/mac 版本的命令行版本才 5-7MB, windows由于有静态编译进来的qt界面, 现在体积有26MB
  4. 用户无需预先安装ffmpeg, 降低用户的使用难度

Documentation

Index

Constants

View Source
const (
	EncryptMethod_NONE       = `NONE`
	EncryptMethod_AES128     = `AES-128`
	EncryptMethod_SIMPLE_AES = `SAMPLE-AES` // TODO
)

https://datatracker.ietf.org/doc/html/rfc8216#section-4.3.2.4

Variables

View Source
var PNG_SIGN = []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}

Functions

func AesDecrypt

func AesDecrypt(seq uint64, encrypted []byte, encInfo *EncryptInfo) ([]byte, error)

func GetFileNameFromUrl

func GetFileNameFromUrl(u string) string

func GetWd

func GetWd() string

func IsContextCancel added in v1.20.0

func IsContextCancel(ctx context.Context) bool

func MergeTsFileListToSingleMp4

func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)

func ParseProxyFormat added in v1.20.0

func ParseProxyFormat(origin string) (after string, urlObj *url.URL, errMsg string)

func RunDownload_Req_ToCurlStr

func RunDownload_Req_ToCurlStr(req StartDownload_Req) string

func UrlHasSuffix

func UrlHasSuffix(urlS string, suff string) bool

Types

type DownloadEnv added in v1.20.0

type DownloadEnv struct {
	// contains filtered or unexported fields
}

func (*DownloadEnv) CloseEnv added in v1.20.0

func (this *DownloadEnv) CloseEnv()

func (*DownloadEnv) GetIsCancel added in v1.20.0

func (this *DownloadEnv) GetIsCancel() bool

func (*DownloadEnv) GetStatus added in v1.20.0

func (this *DownloadEnv) GetStatus() (resp GetStatus_Resp)

func (*DownloadEnv) SleepDur added in v1.20.0

func (this *DownloadEnv) SleepDur(d time.Duration)

func (*DownloadEnv) StartDownload added in v1.20.0

func (this *DownloadEnv) StartDownload(req StartDownload_Req) (errMsg string)

func (*DownloadEnv) WaitDownloadFinish added in v1.20.0

func (this *DownloadEnv) WaitDownloadFinish() GetStatus_Resp

type EncryptInfo

type EncryptInfo struct {
	Method string
	Key    []byte
	Iv     []byte
}

type GetStatus_Resp added in v1.20.0

type GetStatus_Resp struct {
	Percent       int
	Title         string
	StatusBar     string
	IsDownloading bool
	IsCancel      bool
	ErrMsg        string
	IsSkipped     bool
	SaveFileTo    string
}

type M3u8Content

type M3u8Content struct {
	PartList []M3u8Part `json:",omitempty"`
}

func M3u8Parse

func M3u8Parse(content string) (info M3u8Content)

func (M3u8Content) GetPart

func (info M3u8Content) GetPart(tag string) M3u8Part

type M3u8Part

type M3u8Part struct {
	Tag      string            `json:",omitempty"`
	TextFull string            `json:",omitempty"`
	KeyValue map[string]string `json:",omitempty"`
}

type MergeTsFileListToSingleMp4_Req

type MergeTsFileListToSingleMp4_Req struct {
	TsFileList []string
	OutputMp4  string
	Status     *SpeedStatus
	Ctx        context.Context
}

type ParseCurl_Resp

type ParseCurl_Resp struct {
	ErrMsg      string
	DownloadReq StartDownload_Req
}

func ParseCurl

func ParseCurl(cmdList []string) (resp ParseCurl_Resp)

func ParseCurlStr

func ParseCurlStr(s string) (resp ParseCurl_Resp)

type SkipTsUnit added in v1.24.3

type SkipTsUnit struct {
	StartIdx uint32 // 包含
	EndIdx   uint32 // 包含
}

func ParseSkipTsExpr added in v1.24.3

func ParseSkipTsExpr(expr string) (skipList []SkipTsUnit, errMsg string)

type SpeedInfo added in v1.20.0

type SpeedInfo struct {
	BytePerSecond     int
	BytePerSecondText string
	RemainTime        int
	RemainTimeText    string
}

func (SpeedInfo) ToString added in v1.20.0

func (obj SpeedInfo) ToString() string

type SpeedStatus

type SpeedStatus struct {
	Locker    sync.Mutex
	IsRunning bool
	// contains filtered or unexported fields
}

func (*SpeedStatus) DrawProgressBar

func (this *SpeedStatus) DrawProgressBar(total int, current int)

func (*SpeedStatus) GetPercent

func (this *SpeedStatus) GetPercent() (percent int)

func (*SpeedStatus) GetTitle

func (this *SpeedStatus) GetTitle() (title string)

func (*SpeedStatus) ResetTotalBlockCount added in v1.20.0

func (this *SpeedStatus) ResetTotalBlockCount(count int)

func (*SpeedStatus) SetProgressBarTitle

func (this *SpeedStatus) SetProgressBarTitle(title string)

func (*SpeedStatus) SpeedAdd1Block added in v1.20.0

func (this *SpeedStatus) SpeedAdd1Block(byteCount int)

func (*SpeedStatus) SpeedRecent5sGetAndUpdate

func (this *SpeedStatus) SpeedRecent5sGetAndUpdate() (speed SpeedInfo)

func (*SpeedStatus) SpeedResetBytes

func (this *SpeedStatus) SpeedResetBytes()

type StartDownload_Req added in v1.20.0

type StartDownload_Req struct {
	M3u8Url                  string
	Insecure                 bool                // "是否允许不安全的请求(默认为false)"
	SaveDir                  string              // "文件保存路径(默认为当前路径)"
	FileName                 string              // 文件名
	SkipTsExpr               string              // 跳过ts信息,ts编号从1开始,可以以逗号","为分隔符跳过多部分ts,例如: 1,92-100 表示跳过第1号ts、跳过92到100号ts
	SetProxy                 string              //代理
	HeaderMap                map[string][]string // 自定义http头信息
	SkipRemoveTs             bool                // 不删除ts文件
	ProgressBarShow          bool                // 在控制台打印进度条
	ThreadCount              int                 // 线程数
	SkipCacheCheck           bool                // 不缓存已下载的m3u8的文件信息
	SkipMergeTs              bool                // 不合并ts为mp4
	Skip_EXT_X_DISCONTINUITY bool                // 跳过 #EXT-X-DISCONTINUITY 标签包裹的ts
}

type TsInfo

type TsInfo struct {
	Name                        string
	Url                         string
	Seq                         uint64 // 如果是aes加密并且没有iv, 这个seq需要充当iv
	Between_EXT_X_DISCONTINUITY bool
}

TsInfo 用于保存 ts 文件的下载地址和文件名

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL