我尝试创建一个文本视频,其中的文本通过文本转语音进行叙述。
为了创建视频文件,我使用VideoFileWriter
of Aforge.Net
如下:
VideoWriter = new VideoFileWriter();
VideoWriter.Open(CurVideoFile, (int)(Properties.Settings.Default.VideoWidth),
(int)(Properties.Settings.Default.VideoHeight), 25, VideoCodec.MPEG4, 800000);
大声朗读我使用的文字SpeechSynthesizer
类并将输出写入波形流
AudioStream = new FileStream(CurAudioFile, FileMode.Create);
synth.SetOutputToWaveStream(AudioStream);
我想突出显示视频中所说的单词,所以我通过SpeakProgress
event:
void synth_SpeakProgress(object sender, SpeakProgressEventArgs e)
{
curAuidoPosition = e.AudioPosition;
using (Graphics g = Graphics.FromImage(Screen))
{
g.DrawString(e.Text,....);
}
VideoWriter.WriteVideoFrame(Screen, curAuidoPosition);
}
最后,我使用合并视频和音频ffmpeg
using (Process process = new Process())
{
process.StartInfo.FileName = exe_path;
process.StartInfo.Arguments =
string.Format(@"-i ""{0}"" -i ""{1}"" -y -acodec copy -vcodec copy ""{2}""", avi_path, mp3_path, output_file);
// ...
}
问题是,对于 Microsoft Hazel、Zira 和 David 等某些声音,在 Windows 8.1 中,视频与音频不同步,并且音频比显示的字幕快得多。然而,对于 Windows 7 中的声音来说,它是有效的。
如何同步它们,以便它适用于任何操作系统上的任何文本转语音?
看来e.AudioPosition
是不准确的,因为它被提到SpeechSynthesizer 的 SpeakProgressEventArgs 是否不准确? https://stackoverflow.com/q/1718967/2651073,我做了同样的实验,得到了同样的结果。
我注意到如果调整音频格式,我可以接近实际时间,但它不适用于任何声音。
var formats = CurVoice.VoiceInfo.SupportedAudioFormats;
if (formats.Count > 0)
{
var format = formats[0];
reader.SetOutputToWaveFile(CurAudioFile, format);
}
else
{
AudioStream = new FileStream(CurAudioFile, FileMode.Create);
reader.SelectVoice(CurVoice.VoiceInfo.Name);
var fmt = new SpeechAudioFormatInfo(16000, AudioBitsPerSample.Sixteen, AudioChannel.Mono);
// this is more close but not precise yet
MemStream = new MemoryStream();
var mi = reader.GetType().GetMethod("SetOutputStream", BindingFlags.Instance | BindingFlags.NonPublic);
mi.Invoke(reader, new object[] { MemStream, fmt, true, true });
}