123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- package ffmpeg_helper
- import (
- "os"
- "path/filepath"
- "strings"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/common"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/subparser"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_helper"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_parser_hub"
- "github.com/sirupsen/logrus"
- )
- type FFMPEGInfo struct {
- log *logrus.Logger
- VideoFullPath string // 视频文件的路径
- Duration float64 // 视频的时长
- AudioInfoList []AudioInfo // 内置音频列表
- SubtitleInfoList []SubtitleInfo // 内置字幕列表
- ExternalSubInfos []*subparser.FileInfo // 外置字幕列表
- }
- func NewFFMPEGInfo(log *logrus.Logger, videoFullPath string) *FFMPEGInfo {
- return &FFMPEGInfo{
- log: log,
- VideoFullPath: videoFullPath,
- AudioInfoList: make([]AudioInfo, 0),
- SubtitleInfoList: make([]SubtitleInfo, 0),
- ExternalSubInfos: make([]*subparser.FileInfo, 0),
- }
- }
- // GetCacheFolderFPath 获取缓存文件夹的绝对路径,存储在通用的 SubFixCacheFolder 中
- // csf-cache/当前的视频文件名(不带后缀)
- func (f *FFMPEGInfo) GetCacheFolderFPath() (string, error) {
- noExtVideoName := strings.ReplaceAll(filepath.Base(f.VideoFullPath), filepath.Ext(f.VideoFullPath), "")
- return pkg.GetSubFixCacheFolderByName(noExtVideoName)
- }
- // IsExported 是否已经导出过,如果没有导出或者导出不完整为 false
- func (f *FFMPEGInfo) IsExported(exportType ExportType) bool {
- bProcessDone := false
- nowCacheFolder, err := f.GetCacheFolderFPath()
- if err != nil {
- f.log.Errorln("FFMPEGInfo.IsExported.GetCacheFolderFPath", f.VideoFullPath, err.Error())
- return false
- }
- tmpNowExportedMaskFile := filepath.Join(nowCacheFolder, exportedMakeFileName)
- defer func() {
- // 函数执行完毕,再进行 check,是否需要删除 exportedMakeFileName 这个文件
- if bProcessDone == false {
- // 失败就需要删除这个 exportedMakeFileName 文件
- if pkg.IsFile(tmpNowExportedMaskFile) == true {
- _ = os.Remove(tmpNowExportedMaskFile)
- }
- }
- }()
- // 首先存储的缓存目录要存在
- if pkg.IsDir(nowCacheFolder) == false {
- return bProcessDone
- }
- if pkg.IsFile(tmpNowExportedMaskFile) == false {
- return bProcessDone
- }
- switch exportType {
- case Audio:
- // 音频是否导出了
- done := f.isAudioExported(nowCacheFolder)
- if done == false {
- return bProcessDone
- }
- break
- case Subtitle:
- // 字幕都要导出了
- done := f.isSubExported(nowCacheFolder)
- if done == false {
- return bProcessDone
- }
- case SubtitleAndAudio:
- // 音频是否导出了
- done := f.isAudioExported(nowCacheFolder)
- if done == false {
- return bProcessDone
- }
- // 字幕都要导出了
- done = f.isSubExported(nowCacheFolder)
- if done == false {
- return bProcessDone
- }
- default:
- return bProcessDone
- }
- bProcessDone = true
- return bProcessDone
- }
- func (f *FFMPEGInfo) CreateExportedMask() error {
- maskFileFPath, err := f.getExportedMaskFileFPath()
- if err != nil {
- return err
- }
- if pkg.IsFile(maskFileFPath) == false {
- create, err := os.Create(maskFileFPath)
- if err != nil {
- return err
- }
- defer create.Close()
- }
- return nil
- }
- func (f *FFMPEGInfo) getExportedMaskFileFPath() (string, error) {
- nowCacheFolder, err := f.GetCacheFolderFPath()
- if err != nil {
- return "", err
- }
- tmpNowExportedMaskFile := filepath.Join(nowCacheFolder, exportedMakeFileName)
- return tmpNowExportedMaskFile, nil
- }
- // isAudioExported 只需要确认导出了一个音频即可,同时在导出的时候也需要确定只导出一个,且识别出来多个音频,这里会调整到只有一个
- func (f *FFMPEGInfo) isAudioExported(nowCacheFolder string) bool {
- newAudioInfos := make([]AudioInfo, 0)
- for index, audioInfo := range f.AudioInfoList {
- audioFPath := filepath.Join(nowCacheFolder, audioInfo.GetName()+extPCM)
- if pkg.IsFile(audioFPath) == true {
- f.AudioInfoList[index].FullPath = audioFPath
- tmpOneAudioInfo := NewAudioInfo(
- f.AudioInfoList[index].Index,
- f.AudioInfoList[index].CodecName,
- f.AudioInfoList[index].CodecType,
- f.AudioInfoList[index].timeBase,
- f.AudioInfoList[index].startTime,
- f.AudioInfoList[index].language,
- )
- tmpOneAudioInfo.FullPath = audioFPath
- tmpOneAudioInfo.Duration = f.AudioInfoList[index].Duration
- newAudioInfos = append(newAudioInfos, *tmpOneAudioInfo)
- // 替换
- f.AudioInfoList = newAudioInfos
- return true
- }
- }
- return false
- }
- func (f *FFMPEGInfo) isSubExported(nowCacheFolder string) bool {
- for index, subtitleInfo := range f.SubtitleInfoList {
- subSrtFPath := filepath.Join(nowCacheFolder, subtitleInfo.GetName()+common.SubExtSRT)
- if pkg.IsFile(subSrtFPath) == false {
- return false
- } else {
- f.SubtitleInfoList[index].FullPath = subSrtFPath
- }
- subASSFPath := filepath.Join(nowCacheFolder, subtitleInfo.GetName()+common.SubExtASS)
- if pkg.IsFile(subASSFPath) == false {
- return false
- } else {
- f.SubtitleInfoList[index].FullPath = subASSFPath
- }
- }
- return true
- }
- // GetExternalSubInfos 获取外置的字幕信息
- func (f *FFMPEGInfo) GetExternalSubInfos(subParserHub *sub_parser_hub.SubParserHub) error {
- subFiles, err := sub_helper.SearchMatchedSubFileByOneVideo(f.log, f.VideoFullPath)
- if err != nil {
- return err
- }
- for _, subFile := range subFiles {
- bok, subInfo, err := subParserHub.DetermineFileTypeFromFile(subFile)
- if err != nil {
- return err
- }
- if bok == false {
- continue
- }
- f.ExternalSubInfos = append(f.ExternalSubInfos, subInfo)
- }
- return nil
- }
- // 导出成功才生成这个文件
- const exportedMakeFileName = "Exported"
|