查看完整版本: [-- [原创]RM、RMVB、AVI、MKV影音不同步解套(非重製式方法) --]

『漫游』酷论坛 -> 影音精华区 -> [原创]RM、RMVB、AVI、MKV影音不同步解套(非重製式方法) [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

weilai 2003-12-27 21:13

[原创]RM、RMVB、AVI、MKV影音不同步解套(非重製式方法)

使用工具:AviSynth、real media splitter、ReClock、MPC
主要發生原因有兩大類:
[A]壓製時引發(Video及Audio索引鍵問題、I-Frame設置不良)
播放環境引發(PC之Video及Audio解碼時差、Codec安裝不良)

[A]方法除編輯重製外,還可用AviSynth做第二層轉換處理(應為時常把誤認為[A]所以建議用AviSynth)
這裡推薦 ReClock 這個 Filter

先介紹比較簡單的
解套方案
請安裝 ReClock-DSF 並執行 Configure ReClock
如圖游標(鼠標)處取消勾選(因為不希望ReClock-DSF永遠作用於任何播放器)


接著開啟 Media Player Classic
如圖加入濾鏡 ReClock Audio Renderer 並選取 偏好


現在用 Media Player Classic 開啟檔案看看是否改進了

ReClock-DSF 下載點
http://ogo.nerim.net/reclockfilter/main.htm

weilai 2003-12-27 21:14
接者是介紹
[A]解套方案
用到了 avs 腳本,請先確認有安裝 AviSynth
這裡直接告知使用方法
1.先測得影音檔的 FPS 框架率為何?(如圖用右鍵->內容 或用 AVIcodec等工具得知)
右鍵->內容(Windows 檔案總管)

AVIcodec

2.開啟file_info.txt修改內容 -> 存檔
3.最後用播放器開啟avs腳本即可
PS.如果用 Media Player Classic 並且如方案安裝了 ReClock-DSF 可解除使用
,只要取消 ReClock Audio Renderer的勾勾就好了

weilai 2003-12-27 21:15
file_info.txt內容修改例子
(1)要改進 [mp3].avi 之第00:10:20(十分二十秒時以後) 的影音不同步(影像比聲音慢) 2 秒的情形
File_Name = "[mp3].avi"
Delay_Time = 2
Offset_Start_Time = "00:10:20"
Frame_rate = 30

(2)要改進 [ac3].avi 一開始的影音不同步(影像比聲音慢) 2.8 秒的情形
File_Name = "[ac3].avi"
Delay_Time = 2.8
Offset_Start_Time = "00:00:00"
Frame_rate = 24

(3)要改進 [ra].rmvb 之第00:00:30(三十秒時以後) 的影音不同步(聲音比影像慢) 3 秒的情形
File_Name = "[ra].rmvb"
Delay_Time = -3
Offset_Start_Time = "00:00:30"
Frame_rate = 30

(4)要改進 C:\Temp\[mp3].avi 一開始的影音不同步(影像比聲音慢) 3.1 秒的情形
File_Path = "C:\Temp\"
File_Name = "[mp3].avi"
Delay_Time = 3.1
Offset_Start_Time = "00:00:00"
Frame_rate = 30

(5)要改進 [ac3].avi 之第00:20:00(二十分時以後) 的影音不同步(影像比聲音慢) 1.6 秒的情形
並且使用 [mp3].mp3 當作音訊
File_Name = "[ac3].avi"
Audio_Style = "[mp3].mp3"
Delay_Time = 1.6
Offset_Start_Time = "00:20:00"
Frame_rate = 24

注意事項:
1.Frame_rate 這裡一定要填對
2.播放 rm/rmvb 需要系統有安裝 RealMediaSplitter.ax
3.Audio_Style 可用 ac3、mp3、ra、xx.ac3、xx.mp3、xx.ra,如無影音訊分離請保持 ""
4.AviSynth_Plugins_Path 請根據你的AviSynth Plugin 所在位址修改(特別針對上述 3 需求時)
5.針對上述第 3 點分別需要用到 mpasource.dll(mp3)、ac3source.dll(ac3) 等 AviSynth Plugin

後敘:
至於avs腳本原理這裡不做解釋,有興趣者可PM me交流
如有其他使用問題或BUG可將詳細播放情形告知以利排除

weilai 2003-12-27 21:16
[file_info.txt]

#File_Path: 影音檔播放位址(""的話表示和avs腳本及file_info.txt放在一起)。[可不填""或"x:\abc\"或"x:\"]
#File_Name: 可填寫 [.RM、.RMVB、.AVI、.MKV] 等副檔名影音檔(後綴名)。
#Delay_Time: 延遲時間 [範圍: 0 ~ x.x]
#Frame_rate: Frame per sceond。[範圍: 15、24、30、60、120]
#Audio_Style: 音訊型態。[ac3、mp3、ra、xx.ac3、xx.mp3、xx.ra]
#Offset_Start_Time: 開始延遲時間(偏移時間)。["hh:mm:ss",小時:分鐘:秒鐘]
#Property_Revision: 屬性修正旗標(這裡針對Frame_rate)。[True或False]
#AviSynth_Plugins_Path: AviSynth外掛filter的存放位址。
#注意:File_Name、Audio_Style只可出現一次"."並用於區隔副檔名用。

File_Path = ""
File_Name = "a.avi"
Audio_Style = ""

Delay_Time = 0
Offset_Start_Time = "00:00:00"

Frame_rate = 30
Property_Revision = True
If_FilePath_Exist_necessary_word = "\"
AviSynth_Plugins_Path = "C:\Program Files\AviSynth 2.5\plugins\"

weilai 2003-12-27 21:17
[sync.avs]

SetMemoryMax(64)
Import("file_info.txt")
Exist(AviSynth_Plugins_Path + "mpasource.dll") ? \
LoadPlugin(AviSynth_Plugins_Path + "mpasource.dll") : nop
Exist(AviSynth_Plugins_Path + "MPEGDecoder.dll") ? \
LoadPlugin(AviSynth_Plugins_Path + "MPEGDecoder.dll") : nop
Exist(AviSynth_Plugins_Path + "ac3source.dll") ? \
LoadPlugin(AviSynth_Plugins_Path + "ac3source.dll") : nop

Function PropertyRevision_Frame_rate (float F_r) {
ReturnFrame_rate = (F_r == 15) ? 12 : F_r
ReturnFrame_rate = (F_r == 24) ? 23.976 : ReturnFrame_rate
ReturnFrame_rate = (F_r == 30) ? 29.970 : ReturnFrame_rate
ReturnFrame_rate = (F_r == 60) ? 59.94 : ReturnFrame_rate
ReturnFrame_rate = (F_r == 120) ? 59.94 : ReturnFrame_rate
return(default(ReturnFrame_rate, F_r))
}

Function GetFileClip (String F_N, float F_r) {
v = DirectShowSource(F_N, F_r)
ChangeFPS(v, F_r)
AssumeFrameBased(v)
AssumeTFF(v)
AssumeFPS(v, F_r, True)
return(v)
}

Function GetAudio (clip v, String F_P, String F_N, String A_S) {
##求Audio 檔名、副檔名##
A_S_FrontNameChrNum = Findstr(A_S, ".")
A_S_Temp = RightStr(A_S, (StrLen(A_S)- A_S_FrontNameChrNum))
Audio_Style = (A_S_FrontNameChrNum > 0) ? UCase(A_S_Temp) : UCase(A_S)
F_N_FrontNameChrNum = Findstr(F_N, ".")
A_N_Temp = LeftStr(F_N, F_N_FrontNameChrNum)
Audio_Name = (A_S_FrontNameChrNum == 0) ? F_P + A_N_Temp + Audio_Style : F_P + A_S
#####Audio = Vedio######
Audio_Style = (F_N == A_S) ? "Vedio" : Audio_Style
Temp_Clip_Vedio = (F_N == A_S) ? v : nop
#####Audio File存在#####
Temp_Clip_AVI = (Audio_Style == "AVI") ? v : nop
Temp_Clip_MP3 = (Audio_Style == "MP3") ? mpaSource(Audio_Name) : nop
Temp_Clip_AC3 = (Audio_Style == "AC3") ? v.ac3source(Audio_Name).AmplifydB(18,18) : nop
Temp_Clip_WAV = (Audio_Style == "WAV") ? WavSource(F_P + F_N) : nop
Temp_Clip_RA = (Audio_Style == "RA") ? DirectShowSource(Audio_Name, fps= v.framerate, seek= false, audio= True, video= True) : nop

Return_Audio = Eval("Temp_Clip_"+ Audio_Style)
return(Return_Audio)
}

Function ErrorText (int err_num) {
vedio_Subtitle = (err_num == -1) ?
\ "File_info.txt 內的 Offset_Start_Time 時間設定錯誤" :
\ (err_num == 2) ? "檔案沒發現" :
\ ""
vedio_Subtitle = vedio_Subtitle + "avs腳本無作用"
return(vedio_Subtitle)
}

Function Get_Offset_Time(String O_S_T, float F_r) {
Temp_Str = LeftStr(O_S_T, 2)
Time_Temp = Value(LeftStr(Temp_Str, 1)) * 10 + Value(RightStr(Temp_Str, 1))
Hour_Time = (Time_Temp < 60) ? Time_Temp * 360 : -1

Temp_Str = MidStr(O_S_T, 4, 2)
Time_Temp = Value(LeftStr(Temp_Str, 1)) * 10 + Value(RightStr(Temp_Str, 1))
Minute_Time = (Time_Temp < 60) ? Time_Temp * 60 : -1

Temp_Str = RightStr(O_S_T, 2)
Time_Temp = Value(LeftStr(Temp_Str, 1)) * 10 + Value(RightStr(Temp_Str, 1))
Second_Timp = (Time_Temp < 60) ? Time_Temp : -1

Time_Total = ((Hour_Time < 0) || (Minute_Time < 0) || (Second_Timp < 0)) ? -1 : Hour_Time + Minute_Time + Second_Timp
Return_Frame_Count = Int(Time_Total * F_r)
return (Return_Frame_Count)
}

#EX: Vedio_DelayAudio(Vedio, Audio, Offset_Frame, Delay_Time)
Function Vedio_DelayAudio (clip Vedio, clip Audio, Int Offset_Frame, float Delay_Time) {
Global v = Vedio
Global a = !IsClip(Audio) ? Vedio : Audio
Global O_F = Offset_Frame
Global Delay_TimeF = Int(Delay_Time * Vedio.Framerate)
#####Vedio1_NullAudio+Vedio2_Audio2#####
Function DelayTimeis_positive{
Temp_audio = BlankClip(v).Trim(O_F, O_F + Delay_TimeF- 1)
VA_temp1 = AudioDub(v, Temp_audio).Trim(O_F, O_F + Delay_TimeF- 1)
Temp_vedio = v.trim(O_F + Delay_TimeF, v.framecount).KillAudio
VA_temp2 = AudioDub(Temp_vedio, a)
return UnalignedSplice(VA_temp1, VA_temp2)
}
#####Vedio1_Audio1+Vedio2_Audio2########
Function DelayTimeis_negative {
VA_temp1 = v.Trim(O_F, v.Framecount).KillAudio
VA_temp2 = v.Trim(O_F - Delay_TimeF, v.Framecount)
return AudioDub(VA_temp1, VA_temp2)
}
###[Function Vedio_DelayAudio Start]####
Return_VA =
\ (Delay_Time < 0) ? DelayTimeis_negative :
\ (Delay_Time > 0) ? DelayTimeis_positive :
\ AudioDub(Vedio, Audio)

return Return_VA
}

#DivideVedio(Vedio, Audio, Offset_Frame, Delay_Time)
Function DivideVedio (clip v, clip a, Int O_F, float D_T) {
Return_va1 = AudioDub(v, a).Trim(0, O_F- 1)
Return_va2 = AudioDub(v, a).Trim(O_F, v.Framecount).DelayAudio(D_T)
Return_va = Return_va1 + Return_va2
return (Return_va)
}

#####[主程序開始]#####
####參數修正、判斷####
Frame_rate = Property_Revision ? PropertyRevision_Frame_rate(Frame_rate) : Frame_rate
File_Path = File_Path + If_FilePath_Exist_necessary_word
Work_Movie_File = File_Path + File_Name
Work_Audio_File = File_Path + Audio_Style
AudioFile_Exist = Exist(Work_Audio_File)

##獲得Vedio及Audio Clip##
Vedio = GetFileClip(Work_Movie_File, Frame_rate)
Audio = (AudioFile_Exist || (Audio_Style <> "")) ? GetAudio(Vedio, File_Path, File_Name, Audio_Style) : Vedio
IsClip(Audio) ? KillAudio(Vedio) : nop
Offset_Frame = (Delay_Time <> 0) ? Get_Offset_Time(Offset_Start_Time, Frame_rate) : Get_Offset_Time("00:00:00", Frame_rate)

PlayFile =
\ ((Offset_Frame == 0) && (Delay_Time == 0)) ?
\ AudioDub(Vedio, Audio) :
\ (Offset_Frame == 0) ?
\ Vedio_DelayAudio(Vedio, Audio, Offset_Frame, Delay_Time) :
\ (Offset_Frame > 0) ?
\ DivideVedio(Vedio, Audio, Offset_Frame, Delay_Time) :
\ AudioDub(Vedio, Audio)

Offset_Frame < 0 ? PlayFile.Subtitle(ErrorText(-1)) : PlayFile

岚轩 2003-12-31 14:53
weilai,有点复杂的说;)我一般就是用DELAYAUDIO+AUDIODUB,不过多了个音画分离,其实用VMD再DUB一次,只要调整好DELAYAUDIO一样可以的~

weilai 2003-12-31 15:49
引用
最初由 岚轩 发布
weilai,有点复杂的说;)我一般就是用DELAYAUDIO+AUDIODUB,不过多了个音画分离,其实用VMD再DUB一次,只要调整好DELAYAUDIO一样可以的~


寫完自己也這麼覺得
其實主要是邊學邊寫
再加上
.DELAYAUDIO 有一個奇怪的限制(不知說不說的上是 bug ; 用在一開始無偏移時間的使用上)
.一些自動判斷
造成的

weilai 2004-01-03 09:36
這裡加個特例
Q:问个问题,如果rm的声音不同步是越往后不同步越严重,那该怎么做?
A:先試試 方法不行的話試試[A]方法不行的話試試[A]+
原理講解:
其實此情形用 理論因該可以解決
只是 Reclock filter 有一個限制: 應用在解碼後的 PCM 音訊
所以 rm/rmvb 不可行
此時只要用 avs 範本導入
就可透過 avs sever 達到解碼後的音訊為 PCM

file_info.txt內容修改如下
Delay_Time = 0
Offset_Start_Time = "00:00:00"
PS.如果一開始就有延遲現像請用 第3楼的第(2)例

只是真的沒看過 rm 且還會慢慢不同步的情形,所以也不能打包票

yikboon 2004-01-14 14:26
那如果要由rm,rmvb轉換去mpg呢?我有一套动画有这问题,想轉換去vcd file.

collo 2004-01-22 01:21
这个很有价值.
仔细琢磨下.

苍天之泪 2004-01-26 16:06
哇!好东西啊!谢谢,这下我可有办法了!

11joe 2004-01-27 14:36
很好的教程,感谢

Zerozf 2004-01-28 01:51
呵呵,我一般是找另外的版本下来看喽

通灵者 2004-01-29 14:15
好强的贴````不过也太长了~!~``

有时间可以仔细慢慢研究一下`

weilai 2004-01-29 14:46
引用
最初由 通灵者 发布
好强的贴````不过也太长了~!~``

有时间可以仔细慢慢研究一下`


沒辦法沒有合適的上傳空間
貼出.avs內容腳本並非這一帖的本意

目前正製作自動安裝版(setup.exe)
已實驗成功
未來
只要用右鍵-傳送到- xxx 就可不必改 file_info.txt 的 File_xxx 內容
就可開起使用該 .avs
只是受限於 Avisynth 的 DirectShowSource filter function 限制
Frame_rate = xx 還是要自行填寫

講解一下目前進度:
V1.15.10
.取消了 {File_Name、Audio_Style只可出現一次"."並用於區隔副檔名用} 之限制
.字幕自行載入
.使用者末端filter加載
.播放速度調整
.及多項self Function 修訂

未來目標:
.Frame_rate 的自我判讀
.GUI 介面的目標

wxy818 2004-01-29 14:47
每次看到楼主的技术贴,都非常激动,又学了一招呀,不过这次的方法比较复杂,手里有一些不同步的RM文件,正好可以实验一下

summer小鱼 2004-02-07 23:49
555图图全叉烧了 :(
请问下用VirtualDubMod15101怎么解决呢?

Argge 2004-09-25 02:32
现在手头上正好有部RMVB就是影音不同步。。。。

本想试验下,不过看完后晕了半天。。。。。。

偶连怎么压片还不会的说。。。。。。

有没有办法把图补上??有图看至少不会这么晕。。。。。

傳說 2004-10-22 14:48
我想問點解我o個d rm or rmvb[疾疾]地既?

KPM 2004-12-21 16:32
--b
图呢……

lanman 2004-12-24 10:03
感谢分享了!!要认真看看先!!

honduras 2005-03-13 17:23
趕緊來把教學留著
以防萬一啦
感謝教導

efgh2020 2005-04-21 15:22
好贴

有时间我得仔细研究一下

zhanin 2005-09-02 02:54
呵呵~有待研究

万人迷 2007-08-09 06:38
这里才是真正的专业论坛,讲的很好。


查看完整版本: [-- [原创]RM、RMVB、AVI、MKV影音不同步解套(非重製式方法) --] [-- top --]


Powered by phpwind v8.5 Code ©2003-2011 phpwind
Time 0.033345 second(s),query:3 Gzip disabled