sub_file_hash.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package sub_file_hash
  2. import (
  3. "crypto/sha256"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "os"
  8. "github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/common"
  9. "github.com/ChineseSubFinder/ChineseSubFinder/pkg/decode"
  10. )
  11. // Calculate 视频文件的唯一ID,支持内程序内的 Fake 蓝光视频文件路径
  12. func Calculate(filePath string) (string, error) {
  13. bok, _, STREAMDir := decode.IsFakeBDMVWorked(filePath)
  14. if bok == true {
  15. bdmvBigFileFPath, err := getBDMVBigFileFPath(STREAMDir)
  16. if err != nil {
  17. return "", err
  18. }
  19. filePath = bdmvBigFileFPath
  20. }
  21. fp, err := os.Open(filePath)
  22. if err != nil {
  23. return "", err
  24. }
  25. defer func() {
  26. _ = fp.Close()
  27. }()
  28. stat, err := fp.Stat()
  29. if err != nil {
  30. return "", err
  31. }
  32. size := float64(stat.Size())
  33. if size < 0xF000 {
  34. return "", common.VideoFileIsTooSmall
  35. }
  36. samplePositions := [samplingPoints]int64{
  37. 4 * 1024,
  38. int64(math.Floor(size / 4)),
  39. int64(math.Floor(size / 4 * 2)),
  40. int64(math.Floor(size / 4 * 3)),
  41. int64(size - 8*1024)}
  42. fullBlock := make([]byte, samplingPoints*onePointLen)
  43. index := 0
  44. for _, position := range samplePositions {
  45. //f, err := os.Create(filepath.Join("c:\\Tmp", fmt.Sprintf("%d", position)+".videoPart"))
  46. //if err != nil {
  47. // return "", err
  48. //}
  49. oneBlock := make([]byte, onePointLen)
  50. _, err = fp.ReadAt(oneBlock, position)
  51. if err != nil {
  52. //_ = f.Close()
  53. return "", err
  54. }
  55. for _, b := range oneBlock {
  56. fullBlock[index] = b
  57. index++
  58. }
  59. //_, err = f.Write(oneBlock)
  60. //if err != nil {
  61. // return "", err
  62. //}
  63. //_ = f.Close()
  64. }
  65. sum := sha256.Sum256(fullBlock)
  66. return fmt.Sprintf("%x", sum), nil
  67. }
  68. func getBDMVBigFileFPath(STREAMDir string) (string, error) {
  69. // 因为上面可以检测出是否是蓝光电影,这里就是找到蓝光中最大的一个流文件,然后交给后续进行特征提取
  70. pathSep := string(os.PathSeparator)
  71. maxFileFPath := ""
  72. var maxFileSize int64
  73. maxFileSize = 0
  74. files, err := os.ReadDir(STREAMDir)
  75. if err != nil {
  76. return "", err
  77. }
  78. for _, curFile := range files {
  79. fullPath := STREAMDir + pathSep + curFile.Name()
  80. if curFile.IsDir() {
  81. // 只关心这一个文件夹
  82. continue
  83. }
  84. // 文件
  85. info, err := curFile.Info()
  86. if err != nil {
  87. continue
  88. }
  89. if info.Size() > maxFileSize {
  90. maxFileSize = info.Size()
  91. maxFileFPath = fullPath
  92. }
  93. }
  94. if maxFileFPath == "" {
  95. return "", errors.New("getBDMVBigFileFPath no file found")
  96. }
  97. return maxFileFPath, nil
  98. }
  99. const (
  100. samplingPoints = 5
  101. onePointLen = 4 * 1024
  102. )
  103. const checkHash = "f5176762cb6d62471d71511fdddeb7b80c9a7a8939fce5cf172100b4a404a048"