ffmpeg_info.go 5.6 KB

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