northerns74r
9th November 2010, 18:35
Hi all,
I wanted to share with you this script I did these days, in order to hardcode subtitles in videos starting from .srt files.
I know there are plugins or functions which already do this task (TextSub for example), but I had precise needs and I couldn't use it for my task. So I decied to study bit of Avisynth and something else (like GScript etc)...
Here's what it does: it takes video, .srt file, background image for titles and fuse titles on the video. It can handle collisions e vertical alignment in case of single line title (in my case there aren't subtitle with more than two lines).
The real deal (I couldn't do with TextSub) was the overlaying the background image only when subtitles are on screen. At the end, something which can look a bit more professional...
Now the whole workflow is quite faster than doing all the subs in Premiere pasting from a .doc file. Translating in VisualVobSynch is easier when you get confident with it.
This is how the video looks like after hardcoding...
http://forum.videohelp.com/attachments/4167-1289322148/snapshot20101109175107.jpg
#LOCAL PATHS
plugins_dir = "C:\Programmi\AviSynth 2.5\plugins\"
video_dir = "C:\Documents and Settings\aelmi\Desktop\105 - CLUB NATION - CHEMICAL - 10-2010 SYNCH.avi"
sottopancia_dir = "C:\Documents and Settings\aelmi\Desktop\sottopancia1280.tif"
subs_dir = "C:\Documents and Settings\aelmi\Desktop\chemicals.srt"
#STUFF NEEDED
LoadPlugin(plugins_dir+"GScript.dll")
LoadModule("avslib", "base", "constants")
LoadModule("avslib", "base", "conversion")
LoadPackage("avslib", "array")
LoadPackage("avslib", "clip")
LoadModule("avslib", "numeric", "rounding")
#IMPORT OF VIDEO, SUBS AND BACKGROUND
c=DirectShowSource(video_dir, audio=false)
fps = c.framerate
dar = 16/9 #ASSUME 16:9
sar = c.width/c.height
par = dar/sar
bg=ImageReader(sottopancia_dir).BicubicResize(c.Width,c.Height)
bgALPHA=ImageReader(sottopancia_dir,pixel_type="RGB32").ShowAlpha(pixel_type="RGB32").BicubicResize(c.Width,c.Height)
subs = import(subs_dir)
offset_iniziale = FindStr(subs,"1")
sotto_subs = ArrayCreate(midstr(subs, offset_iniziale))
ArrayDelimiterSet(CRLF+CRLF)
#SUB PROPERTIES
y_sottopancia = 0
y_sub = 0.825
font_sub = "LT_50543.TTF"
size_sub = 0.0642
text_color_sub = $FFFFFF
halo_color_sub = $303030
align_sub = 5
lsp_sub = 0.017
font_width_sub = 9
GScript("""
if(sotto_subs.ArrayLen()>0)
{
start_last_frame = -100
end_last_frame = -100
text_last_frame = ""
y_last_sub = y_sub
for(i=0, Floor(Log(sotto_subs.ArrayLen())/Log(10)), 1){
startloop = int(Pow(10,i)-1)
offset = i
if(sotto_subs.ArrayLen()>int(Pow(10,i+1)-3)){
endloop = int(Pow(10,i+1)-2)
}
else {
endloop = sotto_subs.ArrayLen()-1
}
for (j = startloop , endloop, 1)
{
#CALCULATING IN-OUT FRAME OF THE SINGLE SUB
single_sub = sotto_subs.ArrayGet(j)
start_sub_H = MidStr(single_sub, 4+offset,2)
start_sub_M = MidStr(single_sub, 7+offset,2)
start_sub_S = MidStr(single_sub, 10+offset,2)
start_sub_ms = MidStr(single_sub, 13+offset,3)
start_sub_frame = value(start_sub_H)*60*60*fps+value(start_sub_M)*60*fps+value(start_sub_S)*fps+value(start_sub_ms)*fps/1000
end_sub_H = MidStr(single_sub, 21+offset,2)
end_sub_M = MidStr(single_sub, 24+offset,2)
end_sub_S = MidStr(single_sub, 27+offset,2)
end_sub_ms = MidStr(single_sub, 30+offset,3)
end_sub_frame = value(end_sub_H)*60*60*fps+value(end_sub_M)*60*fps+value(end_sub_S)*fps+value(end_sub_ms)*fps/1000
single_sub_text = MidStr(single_sub, 35+offset)
#HANDLING COLLISIONS
if(start_sub_frame<=end_last_frame){
start_sub_frame = start_sub_frame+(start_sub_frame-end_last_frame)+1
}
if((int(start_sub_frame)-int(end_last_frame))<10&&start_sub_frame-end_last_frame>1){
for(k=1,int(start_sub_frame-end_last_frame-1), 1){
c_overlaied=c.Trim(int(end_last_frame+k),int(end_last_frame+k))
c_overlaied=Overlay(x=0,y=y_sottopancia,c_overlaied,bg,mask=bgALPHA)
c=c.Trim(0,int(end_last_frame+k-1))+c_overlaied+c.Trim(int(end_last_frame+k+1),c.framecount)
c=Subtitle(c, text_last_frame, first_frame=int(end_last_frame+k), last_frame=int(end_last_frame+k), y=round(c.Height*y_last_sub+y_sottopancia), font=font_sub, size=round(c.Height*size_sub),
text_color=text_color_sub, halo_color=halo_color_sub, align=align_sub, lsp=round(c.Height*lsp_sub), font_width=round(par*font_width_sub))
}
}
#HANDLING TWO LINES
break=Findstr(single_sub_text, CRLF)
if(break!=0){
single_sub_text=LeftStr(single_sub_text,break-1)+"\n"+Rightstr(single_sub_text, single_sub_text.StrLen-break-1)
}
c_overlaied=c.Trim(int(start_sub_frame),int(end_sub_frame))
c_overlaied=Overlay(x=0,y=y_sottopancia,c_overlaied,bg,mask=bgALPHA)
c=c.Trim(0,int(start_sub_frame-1))+c_overlaied+c.Trim(int(end_sub_frame+1),c.framecount)
#HANDLING VERTICAL ALIGN OF SINGLE LINE SUBS
if(break==0){
y_this_sub = y_sub+0.5*size_sub
}
else{
y_this_sub = y_sub
}
c=Subtitle(c, single_sub_text, first_frame=int(start_sub_frame), last_frame=int(end_sub_frame), y=round(c.Height*y_this_sub+y_sottopancia), font=font_sub, size=round(c.Height*size_sub), text_color=text_color_sub,
halo_color=halo_color_sub, align=align_sub, lsp=round(c.Height*lsp_sub), font_width=round(par*font_width_sub))
start_last_frame = start_sub_frame
end_last_frame = end_sub_frame
text_last_frame = single_sub_text
y_last_sub = y_this_sub
}
}
}
""")
audio=DirectShowSource(video_dir, video=false)
return (AudioDub(c,audio))
The script works fine consider my needs.
Do you have any suggestion?
Anyway at the end of the story I have a problem: when VirtualDub encodes the .avs says "out of memory". Do you know why? Where does the code get heavy to run?
Cheers!
I wanted to share with you this script I did these days, in order to hardcode subtitles in videos starting from .srt files.
I know there are plugins or functions which already do this task (TextSub for example), but I had precise needs and I couldn't use it for my task. So I decied to study bit of Avisynth and something else (like GScript etc)...
Here's what it does: it takes video, .srt file, background image for titles and fuse titles on the video. It can handle collisions e vertical alignment in case of single line title (in my case there aren't subtitle with more than two lines).
The real deal (I couldn't do with TextSub) was the overlaying the background image only when subtitles are on screen. At the end, something which can look a bit more professional...
Now the whole workflow is quite faster than doing all the subs in Premiere pasting from a .doc file. Translating in VisualVobSynch is easier when you get confident with it.
This is how the video looks like after hardcoding...
http://forum.videohelp.com/attachments/4167-1289322148/snapshot20101109175107.jpg
#LOCAL PATHS
plugins_dir = "C:\Programmi\AviSynth 2.5\plugins\"
video_dir = "C:\Documents and Settings\aelmi\Desktop\105 - CLUB NATION - CHEMICAL - 10-2010 SYNCH.avi"
sottopancia_dir = "C:\Documents and Settings\aelmi\Desktop\sottopancia1280.tif"
subs_dir = "C:\Documents and Settings\aelmi\Desktop\chemicals.srt"
#STUFF NEEDED
LoadPlugin(plugins_dir+"GScript.dll")
LoadModule("avslib", "base", "constants")
LoadModule("avslib", "base", "conversion")
LoadPackage("avslib", "array")
LoadPackage("avslib", "clip")
LoadModule("avslib", "numeric", "rounding")
#IMPORT OF VIDEO, SUBS AND BACKGROUND
c=DirectShowSource(video_dir, audio=false)
fps = c.framerate
dar = 16/9 #ASSUME 16:9
sar = c.width/c.height
par = dar/sar
bg=ImageReader(sottopancia_dir).BicubicResize(c.Width,c.Height)
bgALPHA=ImageReader(sottopancia_dir,pixel_type="RGB32").ShowAlpha(pixel_type="RGB32").BicubicResize(c.Width,c.Height)
subs = import(subs_dir)
offset_iniziale = FindStr(subs,"1")
sotto_subs = ArrayCreate(midstr(subs, offset_iniziale))
ArrayDelimiterSet(CRLF+CRLF)
#SUB PROPERTIES
y_sottopancia = 0
y_sub = 0.825
font_sub = "LT_50543.TTF"
size_sub = 0.0642
text_color_sub = $FFFFFF
halo_color_sub = $303030
align_sub = 5
lsp_sub = 0.017
font_width_sub = 9
GScript("""
if(sotto_subs.ArrayLen()>0)
{
start_last_frame = -100
end_last_frame = -100
text_last_frame = ""
y_last_sub = y_sub
for(i=0, Floor(Log(sotto_subs.ArrayLen())/Log(10)), 1){
startloop = int(Pow(10,i)-1)
offset = i
if(sotto_subs.ArrayLen()>int(Pow(10,i+1)-3)){
endloop = int(Pow(10,i+1)-2)
}
else {
endloop = sotto_subs.ArrayLen()-1
}
for (j = startloop , endloop, 1)
{
#CALCULATING IN-OUT FRAME OF THE SINGLE SUB
single_sub = sotto_subs.ArrayGet(j)
start_sub_H = MidStr(single_sub, 4+offset,2)
start_sub_M = MidStr(single_sub, 7+offset,2)
start_sub_S = MidStr(single_sub, 10+offset,2)
start_sub_ms = MidStr(single_sub, 13+offset,3)
start_sub_frame = value(start_sub_H)*60*60*fps+value(start_sub_M)*60*fps+value(start_sub_S)*fps+value(start_sub_ms)*fps/1000
end_sub_H = MidStr(single_sub, 21+offset,2)
end_sub_M = MidStr(single_sub, 24+offset,2)
end_sub_S = MidStr(single_sub, 27+offset,2)
end_sub_ms = MidStr(single_sub, 30+offset,3)
end_sub_frame = value(end_sub_H)*60*60*fps+value(end_sub_M)*60*fps+value(end_sub_S)*fps+value(end_sub_ms)*fps/1000
single_sub_text = MidStr(single_sub, 35+offset)
#HANDLING COLLISIONS
if(start_sub_frame<=end_last_frame){
start_sub_frame = start_sub_frame+(start_sub_frame-end_last_frame)+1
}
if((int(start_sub_frame)-int(end_last_frame))<10&&start_sub_frame-end_last_frame>1){
for(k=1,int(start_sub_frame-end_last_frame-1), 1){
c_overlaied=c.Trim(int(end_last_frame+k),int(end_last_frame+k))
c_overlaied=Overlay(x=0,y=y_sottopancia,c_overlaied,bg,mask=bgALPHA)
c=c.Trim(0,int(end_last_frame+k-1))+c_overlaied+c.Trim(int(end_last_frame+k+1),c.framecount)
c=Subtitle(c, text_last_frame, first_frame=int(end_last_frame+k), last_frame=int(end_last_frame+k), y=round(c.Height*y_last_sub+y_sottopancia), font=font_sub, size=round(c.Height*size_sub),
text_color=text_color_sub, halo_color=halo_color_sub, align=align_sub, lsp=round(c.Height*lsp_sub), font_width=round(par*font_width_sub))
}
}
#HANDLING TWO LINES
break=Findstr(single_sub_text, CRLF)
if(break!=0){
single_sub_text=LeftStr(single_sub_text,break-1)+"\n"+Rightstr(single_sub_text, single_sub_text.StrLen-break-1)
}
c_overlaied=c.Trim(int(start_sub_frame),int(end_sub_frame))
c_overlaied=Overlay(x=0,y=y_sottopancia,c_overlaied,bg,mask=bgALPHA)
c=c.Trim(0,int(start_sub_frame-1))+c_overlaied+c.Trim(int(end_sub_frame+1),c.framecount)
#HANDLING VERTICAL ALIGN OF SINGLE LINE SUBS
if(break==0){
y_this_sub = y_sub+0.5*size_sub
}
else{
y_this_sub = y_sub
}
c=Subtitle(c, single_sub_text, first_frame=int(start_sub_frame), last_frame=int(end_sub_frame), y=round(c.Height*y_this_sub+y_sottopancia), font=font_sub, size=round(c.Height*size_sub), text_color=text_color_sub,
halo_color=halo_color_sub, align=align_sub, lsp=round(c.Height*lsp_sub), font_width=round(par*font_width_sub))
start_last_frame = start_sub_frame
end_last_frame = end_sub_frame
text_last_frame = single_sub_text
y_last_sub = y_this_sub
}
}
}
""")
audio=DirectShowSource(video_dir, video=false)
return (AudioDub(c,audio))
The script works fine consider my needs.
Do you have any suggestion?
Anyway at the end of the story I have a problem: when VirtualDub encodes the .avs says "out of memory". Do you know why? Where does the code get heavy to run?
Cheers!