Browse Source

新增判断视频与字幕是否匹配的函数

Signed-off-by: allan716 <[email protected]>
allan716 3 years ago
parent
commit
5f2e2ea7df

+ 163 - 0
TestCode/test_statistics_subs_score.go

@@ -19,6 +19,63 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/pkg/vad"
 )
 
+func statistics_subs_score_one(baseAudioFileFPath, baseSubFileFPath, srcSubFileFPath string) {
+
+	audioVADInfos, err := vad.GetVADInfoFromAudio(vad.AudioInfo{
+		FileFullPath: baseAudioFileFPath,
+		SampleRate:   16000,
+		BitDepth:     16,
+	}, true)
+	if err != nil {
+		return
+	}
+
+	subParserHub := sub_parser_hub.NewSubParserHub(
+		log_helper.GetLogger4Tester(),
+		ass.NewParser(log_helper.GetLogger4Tester()),
+		srt.NewParser(log_helper.GetLogger4Tester()),
+	)
+	bFind, infoBase, err := subParserHub.DetermineFileTypeFromFile(baseSubFileFPath)
+	if err != nil {
+		return
+	}
+	if bFind == false {
+		return
+	}
+
+	bFind, srcBase, err := subParserHub.DetermineFileTypeFromFile(srcSubFileFPath)
+	if err != nil {
+		return
+	}
+	if bFind == false {
+		return
+	}
+
+	s := sub_timeline_fixer.NewSubTimelineFixerHelperEx(log_helper.GetLogger4Tester(), *settings.NewTimelineFixerSettings())
+	// path X:\电影\21座桥 (2019)\21座桥 (2019) 720p AAC.chinese(简,subhd).ass
+	// 音频处理
+	cloneSrcBase := clone.Clone(srcBase).(*subparser.FileInfo)
+	bok, _, pipeResultAudio, err := s.ProcessByAudioVAD(audioVADInfos, cloneSrcBase)
+	if err != nil {
+		return
+	}
+	if bok == false {
+		return
+	}
+	// 字幕处理
+	cloneSrcBase = clone.Clone(srcBase).(*subparser.FileInfo)
+	bok, _, pipeResultSub, err := s.ProcessBySubFileInfo(infoBase, cloneSrcBase)
+	if err != nil {
+		return
+	}
+	if bok == false {
+		return
+	}
+
+	println(fmt.Sprintf("Audio Score: %f  Offset:%f\n", pipeResultAudio.Score, pipeResultAudio.GetOffsetTime()))
+	println(fmt.Sprintf("Sub Score: %f  Offset:%f\n", pipeResultSub.Score, pipeResultSub.GetOffsetTime()))
+}
+
 func statistics_subs_score(baseAudioFileFPath, baseSubFileFPath, subSearchRootPath string) {
 
 	f := excelize.NewFile()
@@ -148,3 +205,109 @@ func statistics_subs_score(baseAudioFileFPath, baseSubFileFPath, subSearchRootPa
 		return
 	}
 }
+
+func statistics_subs_score_is_match(videoFPath, subSearchRootPath string) {
+
+	s := sub_timeline_fixer.NewSubTimelineFixerHelperEx(log_helper.GetLogger4Tester(), *settings.NewTimelineFixerSettings())
+	bok, audioVADInfos, infoBase, err := s.IsVideoCanExportSubtitleAndAudio(videoFPath)
+	if err != nil {
+		return
+	}
+	if bok == false {
+		return
+	}
+
+	f := excelize.NewFile()
+	// Create a new sheet.
+	sheetName := filepath.Base(subSearchRootPath)
+	newSheet := f.NewSheet(sheetName)
+	err = f.SetCellValue(sheetName, fmt.Sprintf("A%d", 1), "SubFPath")
+	if err != nil {
+		return
+	}
+	err = f.SetCellValue(sheetName, fmt.Sprintf("B%d", 1), "AudioScore")
+	if err != nil {
+		return
+	}
+	err = f.SetCellValue(sheetName, fmt.Sprintf("C%d", 1), "AudioOffset")
+	if err != nil {
+		return
+	}
+	err = f.SetCellValue(sheetName, fmt.Sprintf("D%d", 1), "SubScore")
+	if err != nil {
+		return
+	}
+	err = f.SetCellValue(sheetName, fmt.Sprintf("E%d", 1), "SubOffset")
+	if err != nil {
+		return
+	}
+	err = f.SetCellValue(sheetName, fmt.Sprintf("F%d", 1), "IsMatch")
+	if err != nil {
+		return
+	}
+
+	subCounter := 1
+	err = filepath.Walk(subSearchRootPath,
+		func(path string, info os.FileInfo, err error) error {
+			if err != nil {
+				return err
+			}
+
+			if info.IsDir() == true {
+				return nil
+			}
+			if sub_parser_hub.IsSubExtWanted(info.Name()) == false {
+				return nil
+			}
+
+			bok, audioScore, audioOffset, subScore, subOffset, err := s.IsMatchBySubFile(audioVADInfos, infoBase, path, 40000, 2)
+			if err != nil {
+				return nil
+			}
+
+			subCounter++
+			err = f.SetCellValue(sheetName, fmt.Sprintf("A%d", subCounter+1), info.Name())
+			if err != nil {
+				return nil
+			}
+			err = f.SetCellValue(sheetName, fmt.Sprintf("B%d", subCounter+1), audioScore)
+			if err != nil {
+				return nil
+			}
+			err = f.SetCellValue(sheetName, fmt.Sprintf("C%d", subCounter+1), audioOffset)
+			if err != nil {
+				return nil
+			}
+			err = f.SetCellValue(sheetName, fmt.Sprintf("D%d", subCounter+1), subScore)
+			if err != nil {
+				return nil
+			}
+			err = f.SetCellValue(sheetName, fmt.Sprintf("E%d", subCounter+1), subOffset)
+			if err != nil {
+				return nil
+			}
+			iTrue := 0
+			if bok == true {
+				iTrue = 1
+			}
+			err = f.SetCellValue(sheetName, fmt.Sprintf("F%d", subCounter+1), iTrue)
+			if err != nil {
+				return nil
+			}
+
+			fmt.Println(subCounter, path, info.Size())
+
+			return nil
+		})
+	if err != nil {
+		fmt.Println("Walk", err)
+		return
+	}
+
+	f.SetActiveSheet(newSheet)
+	err = f.SaveAs(fmt.Sprintf("%s.xlsx", filepath.Base(videoFPath)))
+	if err != nil {
+		fmt.Println("SaveAs", err)
+		return
+	}
+}

+ 58 - 0
TestCode/test_statistics_subs_score_test.go

@@ -27,3 +27,61 @@ func Test_statistics_subs_score(t *testing.T) {
 		})
 	}
 }
+
+func Test_statistics_subs_score_one(t *testing.T) {
+	type args struct {
+		baseAudioFileFPath string
+		baseSubFileFPath   string
+		srcSubFileFPath    string
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "Test_statistics_subs_score_one",
+			args: args{
+				baseAudioFileFPath: "C:\\temp\\video\\base\\RM-S05E01\\未知语言_1.pcm",
+				baseSubFileFPath:   "C:\\temp\\video\\base\\RM-S05E01\\英_2.srt",
+				srcSubFileFPath:    "C:\\temp\\video\\Rick and Morty - S05E01 - Mort Dinner Rick Andre WEBDL-1080p.chinese(简英,fix).srt",
+			},
+		},
+		{
+			name: "Test_statistics_subs_score_one2",
+			args: args{
+				baseAudioFileFPath: "C:\\temp\\video\\base\\RM-S05E01\\未知语言_1.pcm",
+				baseSubFileFPath:   "C:\\temp\\video\\base\\RM-S05E01\\英_2.srt",
+				srcSubFileFPath:    "C:\\temp\\video\\The Boys - S03E01 - Payback WEBRip-1080p.chinese(简英,subhd).ass",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			statistics_subs_score_one(tt.args.baseAudioFileFPath, tt.args.baseSubFileFPath, tt.args.srcSubFileFPath)
+		})
+	}
+}
+
+func Test_statistics_subs_score_is_match(t *testing.T) {
+	type args struct {
+		videoFPath        string
+		subSearchRootPath string
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "Test_statistics_subs_score_is_match",
+			args: args{
+				videoFPath:        "C:\\temp\\video\\Rick and Morty - S05E01 - Mort Dinner Rick Andre WEBDL-1080p.mkv",
+				subSearchRootPath: "X:\\连续剧\\瑞克和莫蒂 (2013)",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			statistics_subs_score_is_match(tt.args.videoFPath, tt.args.subSearchRootPath)
+		})
+	}
+}

+ 87 - 12
pkg/logic/sub_timeline_fixer/SubTimelineFixerHelperEx.go

@@ -220,21 +220,96 @@ func (s SubTimelineFixerHelperEx) ProcessByAudioFile(baseAudioFileFPath, srcSubF
 	return s.ProcessByAudioVAD(audioVADInfos, infoSrc)
 }
 
-func (s SubTimelineFixerHelperEx) IsMatchBySubFile(baseSubFileFPath, srcSubFileFPath string) (bool, error) {
-
-	//bProcess, _, pipeResultMax, err := s.ProcessBySubFile(baseSubFileFPath, srcSubFileFPath)
-	//if err != nil {
-	//	return false, fmt.Errorf("ProcessBySubFile error: %v", err)
-	//}
-	//if bProcess == false {
-	//	return false, nil
-	//}
-	return false, nil
+func (s SubTimelineFixerHelperEx) IsVideoCanExportSubtitleAndAudio(videoFileFullPath string) (bool, []vad.VADInfo, *subparser.FileInfo, error) {
+
+	// 先尝试获取内置字幕的信息
+	bok, ffmpegInfo, err := s.ffmpegHelper.GetFFMPEGInfo(videoFileFullPath, ffmpeg_helper.SubtitleAndAudio)
+	if err != nil {
+		return false, nil, nil, err
+	}
+	if bok == false {
+		return false, nil, nil, nil
+	}
+	// ---------------------------------------------------------------------------------------
+	// 音频
+	if len(ffmpegInfo.AudioInfoList) <= 0 {
+		return false, nil, nil, nil
+	}
+	audioVADInfos, err := vad.GetVADInfoFromAudio(vad.AudioInfo{
+		FileFullPath: ffmpegInfo.AudioInfoList[0].FullPath,
+		SampleRate:   16000,
+		BitDepth:     16,
+	}, true)
+	if err != nil {
+		return false, nil, nil, err
+	}
+	// ---------------------------------------------------------------------------------------
+	// 字幕
+	if len(ffmpegInfo.SubtitleInfoList) <= 0 {
+		return false, nil, nil, nil
+	}
+	// 使用内置的字幕进行时间轴的校正,这里需要考虑一个问题,内置的字幕可能是有问题的(先考虑一种,就是字幕的长度不对,是一小段的)
+	// 那么就可以比较多个内置字幕的大小选择大的去使用
+	// 如果有多个内置的字幕,还是要判断下的,选体积最大的那个吧
+	fileSizes := treemap.NewWith(utils.Int64Comparator)
+	for index, info := range ffmpegInfo.SubtitleInfoList {
+		fi, err := os.Stat(info.FullPath)
+		if err != nil {
+			fileSizes.Put(0, index)
+		} else {
+			fileSizes.Put(fi.Size(), index)
+		}
+	}
+	_, index := fileSizes.Max()
+	baseSubFPath := ffmpegInfo.SubtitleInfoList[index.(int)].FullPath
+	bFind, infoBase, err := s.subParserHub.DetermineFileTypeFromFile(baseSubFPath)
+	if err != nil {
+		return false, nil, nil, err
+	}
+	if bFind == false {
+		return false, nil, nil, nil
+	}
+	// ---------------------------------------------------------------------------------------
+
+	return true, audioVADInfos, infoBase, nil
 }
 
-func (s SubTimelineFixerHelperEx) IsMatchBySubFileInfo(infoBase *subparser.FileInfo, srcSubFileFPath string) (bool, error) {
+func (s SubTimelineFixerHelperEx) IsMatchBySubFile(audioVADInfos []vad.VADInfo, infoBase *subparser.FileInfo, srcSubFileFPath string, minScore float64, offsetRange float64) (bool, float64, float64, float64, float64, error) {
 
-	return false, nil
+	bFind, srcBase, err := s.subParserHub.DetermineFileTypeFromFile(srcSubFileFPath)
+	if err != nil {
+		return false, 0, 0, 0, 0, err
+	}
+	if bFind == false {
+		return false, 0, 0, 0, 0, nil
+	}
+	// ---------------------------------------------------------------------------------------
+	// 音频
+	s.log.Infoln("IsMatchBySubFile:", srcSubFileFPath)
+	bProcess, _, pipeResultMaxAudio, err := s.ProcessByAudioVAD(audioVADInfos, srcBase)
+	if err != nil {
+		return false, 0, 0, 0, 0, err
+	}
+	if bProcess == false {
+		return false, 0, 0, 0, 0, nil
+	}
+	// ---------------------------------------------------------------------------------------
+	// 字幕
+	bProcess, _, pipeResultMaxSub, err := s.ProcessBySubFileInfo(infoBase, srcBase)
+	if err != nil {
+		return false, 0, 0, 0, 0, err
+	}
+	if bProcess == false {
+		return false, 0, 0, 0, 0, nil
+	}
+	// ---------------------------------------------------------------------------------------
+	if pipeResultMaxAudio.Score < minScore || pipeResultMaxSub.Score < minScore {
+		return false, pipeResultMaxAudio.Score, pipeResultMaxAudio.GetOffsetTime(), pipeResultMaxSub.Score, pipeResultMaxSub.GetOffsetTime(), nil
+	}
+	if math.Abs(pipeResultMaxAudio.GetOffsetTime()-pipeResultMaxSub.GetOffsetTime()) > offsetRange {
+		return false, pipeResultMaxAudio.Score, pipeResultMaxAudio.GetOffsetTime(), pipeResultMaxSub.Score, pipeResultMaxSub.GetOffsetTime(), nil
+	}
+	return true, pipeResultMaxAudio.Score, pipeResultMaxAudio.GetOffsetTime(), pipeResultMaxSub.Score, pipeResultMaxSub.GetOffsetTime(), nil
 }
 
 func (s SubTimelineFixerHelperEx) changeTimeLineAndSave(infoSrc *subparser.FileInfo, pipeResult sub_timeline_fixer.PipeResult, desSubSaveFPath string) error {