ffmpeg_info.go 5.6 KB

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