ffmpeg_info.go 5.6 KB

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