ffmpeg_info.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. package ffmpeg_helper
  2. import (
  3. "github.com/allanpk716/ChineseSubFinder/pkg"
  4. "github.com/allanpk716/ChineseSubFinder/pkg/types/common"
  5. "github.com/allanpk716/ChineseSubFinder/pkg/types/subparser"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "github.com/allanpk716/ChineseSubFinder/pkg/my_util"
  10. "github.com/allanpk716/ChineseSubFinder/pkg/sub_helper"
  11. "github.com/allanpk716/ChineseSubFinder/pkg/sub_parser_hub"
  12. "github.com/sirupsen/logrus"
  13. )
  14. type FFMPEGInfo struct {
  15. log *logrus.Logger
  16. VideoFullPath string // 视频文件的路径
  17. Duration float64 // 视频的时长
  18. AudioInfoList []AudioInfo // 内置音频列表
  19. SubtitleInfoList []SubtitleInfo // 内置字幕列表
  20. ExternalSubInfos []*subparser.FileInfo // 外置字幕列表
  21. }
  22. func NewFFMPEGInfo(log *logrus.Logger, videoFullPath string) *FFMPEGInfo {
  23. return &FFMPEGInfo{
  24. log: log,
  25. VideoFullPath: videoFullPath,
  26. AudioInfoList: make([]AudioInfo, 0),
  27. SubtitleInfoList: make([]SubtitleInfo, 0),
  28. ExternalSubInfos: make([]*subparser.FileInfo, 0),
  29. }
  30. }
  31. // GetCacheFolderFPath 获取缓存文件夹的绝对路径,存储在通用的 SubFixCacheFolder 中
  32. // csf-cache/当前的视频文件名(不带后缀)
  33. func (f *FFMPEGInfo) GetCacheFolderFPath() (string, error) {
  34. noExtVideoName := strings.ReplaceAll(filepath.Base(f.VideoFullPath), filepath.Ext(f.VideoFullPath), "")
  35. return pkg.GetSubFixCacheFolderByName(noExtVideoName)
  36. }
  37. // IsExported 是否已经导出过,如果没有导出或者导出不完整为 false
  38. func (f *FFMPEGInfo) IsExported(exportType ExportType) bool {
  39. bProcessDone := false
  40. nowCacheFolder, err := f.GetCacheFolderFPath()
  41. if err != nil {
  42. f.log.Errorln("FFMPEGInfo.IsExported.GetCacheFolderFPath", f.VideoFullPath, err.Error())
  43. return false
  44. }
  45. tmpNowExportedMaskFile := filepath.Join(nowCacheFolder, exportedMakeFileName)
  46. defer func() {
  47. // 函数执行完毕,再进行 check,是否需要删除 exportedMakeFileName 这个文件
  48. if bProcessDone == false {
  49. // 失败就需要删除这个 exportedMakeFileName 文件
  50. if my_util.IsFile(tmpNowExportedMaskFile) == true {
  51. _ = os.Remove(tmpNowExportedMaskFile)
  52. }
  53. }
  54. }()
  55. // 首先存储的缓存目录要存在
  56. if my_util.IsDir(nowCacheFolder) == false {
  57. return bProcessDone
  58. }
  59. if my_util.IsFile(tmpNowExportedMaskFile) == false {
  60. return bProcessDone
  61. }
  62. switch exportType {
  63. case Audio:
  64. // 音频是否导出了
  65. done := f.isAudioExported(nowCacheFolder)
  66. if done == false {
  67. return bProcessDone
  68. }
  69. break
  70. case Subtitle:
  71. // 字幕都要导出了
  72. done := f.isSubExported(nowCacheFolder)
  73. if done == false {
  74. return bProcessDone
  75. }
  76. case SubtitleAndAudio:
  77. // 音频是否导出了
  78. done := f.isAudioExported(nowCacheFolder)
  79. if done == false {
  80. return bProcessDone
  81. }
  82. // 字幕都要导出了
  83. done = f.isSubExported(nowCacheFolder)
  84. if done == false {
  85. return bProcessDone
  86. }
  87. default:
  88. return bProcessDone
  89. }
  90. bProcessDone = true
  91. return bProcessDone
  92. }
  93. func (f FFMPEGInfo) CreateExportedMask() error {
  94. maskFileFPath, err := f.getExportedMaskFileFPath()
  95. if err != nil {
  96. return err
  97. }
  98. if my_util.IsFile(maskFileFPath) == false {
  99. create, err := os.Create(maskFileFPath)
  100. if err != nil {
  101. return err
  102. }
  103. defer create.Close()
  104. }
  105. return nil
  106. }
  107. func (f FFMPEGInfo) getExportedMaskFileFPath() (string, error) {
  108. nowCacheFolder, err := f.GetCacheFolderFPath()
  109. if err != nil {
  110. return "", err
  111. }
  112. tmpNowExportedMaskFile := filepath.Join(nowCacheFolder, exportedMakeFileName)
  113. return tmpNowExportedMaskFile, nil
  114. }
  115. // isAudioExported 只需要确认导出了一个音频即可,同时在导出的时候也需要确定只导出一个,且识别出来多个音频,这里会调整到只有一个
  116. func (f *FFMPEGInfo) isAudioExported(nowCacheFolder string) bool {
  117. newAudioInfos := make([]AudioInfo, 0)
  118. for index, audioInfo := range f.AudioInfoList {
  119. audioFPath := filepath.Join(nowCacheFolder, audioInfo.GetName()+extPCM)
  120. if my_util.IsFile(audioFPath) == true {
  121. f.AudioInfoList[index].FullPath = audioFPath
  122. tmpOneAudioInfo := NewAudioInfo(
  123. f.AudioInfoList[index].Index,
  124. f.AudioInfoList[index].CodecName,
  125. f.AudioInfoList[index].CodecType,
  126. f.AudioInfoList[index].timeBase,
  127. f.AudioInfoList[index].startTime,
  128. f.AudioInfoList[index].language,
  129. )
  130. tmpOneAudioInfo.FullPath = audioFPath
  131. tmpOneAudioInfo.Duration = f.AudioInfoList[index].Duration
  132. newAudioInfos = append(newAudioInfos, *tmpOneAudioInfo)
  133. // 替换
  134. f.AudioInfoList = newAudioInfos
  135. return true
  136. }
  137. }
  138. return false
  139. }
  140. func (f *FFMPEGInfo) isSubExported(nowCacheFolder string) bool {
  141. for index, subtitleInfo := range f.SubtitleInfoList {
  142. subSrtFPath := filepath.Join(nowCacheFolder, subtitleInfo.GetName()+common.SubExtSRT)
  143. if my_util.IsFile(subSrtFPath) == false {
  144. return false
  145. } else {
  146. f.SubtitleInfoList[index].FullPath = subSrtFPath
  147. }
  148. subASSFPath := filepath.Join(nowCacheFolder, subtitleInfo.GetName()+common.SubExtASS)
  149. if my_util.IsFile(subASSFPath) == false {
  150. return false
  151. } else {
  152. f.SubtitleInfoList[index].FullPath = subASSFPath
  153. }
  154. }
  155. return true
  156. }
  157. // GetExternalSubInfos 获取外置的字幕信息
  158. func (f *FFMPEGInfo) GetExternalSubInfos(subParserHub *sub_parser_hub.SubParserHub) error {
  159. subFiles, err := sub_helper.SearchMatchedSubFileByOneVideo(f.log, f.VideoFullPath)
  160. if err != nil {
  161. return err
  162. }
  163. for _, subFile := range subFiles {
  164. bok, subInfo, err := subParserHub.DetermineFileTypeFromFile(subFile)
  165. if err != nil {
  166. return err
  167. }
  168. if bok == false {
  169. continue
  170. }
  171. f.ExternalSubInfos = append(f.ExternalSubInfos, subInfo)
  172. }
  173. return nil
  174. }
  175. // 导出成功才生成这个文件
  176. const exportedMakeFileName = "Exported"