怎样编程实现swf文件到mp3文件的批量转换?(200分)

  • 主题发起人 主题发起人 zoutie
  • 开始时间 开始时间
Z

zoutie

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵,手头有上千个flash文件需要提取其中的声音,用软件一个一个得累死人的,
我想能否写个程序实现SwfToMp3的批量转换功能?现在首先得实现从swf文件中提
取声音保存为MP3,在delphi有办法实现吗?
 
我也需要,如果有请发送到klucy@eyou.com谢谢!
 
批量处理时,当swf文件<25时正常,>25个swf文件时就出错,哪里不对呀?

unit SWFBlue_u1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ActnList, StdActns, StdCtrls, Buttons, ShlObj, Zlib, Psock,
NMpop3;

type
TMain = class(TForm)
b_open: TButton;
Button3: TButton;
Label1: TLabel;
Label3: TLabel;
OpenDialog1: TOpenDialog;
Label4: TLabel;
e_dir2: TEdit;
SpeedButton1: TSpeedButton;
Label5: TLabel;
Label2: TLabel;
procedure b_openClick(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
FileLength : LongWord;
//SWF文件尺寸
FileBuf : Array of Byte;
//将SWF文件读入内存存放
end;


var
Main: TMain;

implementation

{$R *.dfm}

procedure TMain.b_openClick(Sender: TObject);
var
f : File;
i : smallint ;
fws : string[3];
//标示信息
version : Byte;
//SWF文件版本号
b,b1,b2 : Byte;
Buf : Array of Byte;
FrameRate : real;
//速率
FrameCount : Word;
//总帧数
s : string;
TagID : Word;
//Tag标示
TagLength : LongWord;
//Tag长度
CurrentPos,FileLengthPos,TagPos,tmpPos : Integer;
//CurrentPos记录当前读写位置
//FileLengthPos记录FileLength参数位置
//TagPos记录当前TagID位置
Filename : string;
//存放SWF文件名(去掉了路径和扩展名)
l : LongWord;
SoundID : Word;
//Event Sounds的Sound ID
SoundInfo : Byte;
//Event Sounds的声音信息
SoundSampleCount : LongWord;
StreamHeadb1,StreamHeadb2 : Byte;
//Stream Sounds的声音信息
StreamSoundSampleCount : Word;
SoundFile : string;
//记录生成的声音文件的扩展名,根据None、ADPCM和mp3不同分为.WAV和.MP3
SoundCount : Word;
//Stream Sounds类型的文件计数
fw : File;
Unknow1 : Word;
UnKnow2 : LongWord;

begin


if not OpenDialog1.Execute then
exit;

b_open.Caption :='正在处理你所选择的SWF文件,请稍等片刻!';
b_open.Enabled :=false;
Button3.Enabled :=false;

for i:=0 to OpenDialog1.files.count-1do


begin


Application.ProcessMessages;

FileMode:=fmOpenRead;
AssignFile(f,OpenDialog1.files.Strings);
Reset(f,1);
SetLength(FileBuf,FileSize(f));
BlockRead(f,FileBuf[0],Filesize(f));
//将文件读入内存
CloseFile(f);
//下面为读取SWF文件的文件头Header部分
CurrentPos:=0;
//读取'FWS'标示
SetLength(fws,3);
Move(FileBuf[CurrentPos],fws[1],3);
Inc(CurrentPos,3);
if fws<>'FWS' then

begin

SetLength(FileBuf,0);
ShowMessage(OpenDialog1.Files.Strings+'不是Flash SWF文件!');

if i=OpenDialog1.files.count-1 then

begin

b_open.Caption :='选择SWF文件并提取其所含声音文件';
b_open.Enabled :=true;
Button3.Enabled :=true;
exit;
end else
continue;

end;


//读取版本号
Move(FileBuf[CurrentPos],version,Sizeof(version));
Inc(CurrentPos,Sizeof(version));
//if Version<5 then
begin

// SetLength(FileBuf,0);
// ShowMessage('该SWF文件不是Flash 5以上版本,本程序当前仅识别Flash 5以上格式SWF文件!');
// exit;
//end;

//读取SWF文件长度
FileLengthPos:=CurrentPos;
Move(FileBuf[CurrentPos],FileLength,Sizeof(FileLength));
Inc(CurrentPos,Sizeof(FileLength));
//读取XMin,XMax,YMin,YMax
//这里仅读出此四个值的存贮字节存放到Buf中,没有计算它们的实际值
Move(FileBuf[CurrentPos],b,1);
Inc(CurrentPos,1);
b2:=b shr 3;
//得到Bit位数
b2:=5+b2*4;
while (b2 mod 8)<>0do
Inc(b2);
//计算共有多少Bit位数
b2:=(b2 div 8)-1;
//计算共有多少字节Byte
SetLength(Buf,b2+1);
Buf[0]:=b;
Move(FileBuf[CurrentPos],Buf[1],b2);
Inc(CurrentPos,b2);
//读取FrameRate,b2为小数点前部分,b1为小数点后部分
Move(FileBuf[CurrentPos],b1,Sizeof(b1));
Inc(CurrentPos,Sizeof(b1));
Move(FileBuf[CurrentPos],b2,Sizeof(b2));
Inc(CurrentPos,Sizeof(b2));
s:=IntToStr(b2)+'.'+IntToStr(b1);
FrameRate:=StrToFloat(s);
//读取总帧数FrameCount
Move(FileBuf[CurrentPos],FrameCount,Sizeof(FrameCount));
Inc(CurrentPos,Sizeof(FrameCount));

//下面为读取SWF文件的文件内容Tag部分
s:=OpenDialog1.Files.Strings;
s:=ExtractFileName(s);
while Pos('.',s)<>0do
s:=Copy(s,1,Pos('.',s)-1);
Filename:=s;
SetLength(Buf,0);
SoundFile:='.WAV';
SoundCount:=1;
repeat
TagPos:=CurrentPos;
//读取TagID并得到TagLength
Move(FileBuf[CurrentPos],TagID,Sizeof(TagID));
Inc(CurrentPos,Sizeof(TagID));
TagLength:=TagID and $3F;
TagID:=TagID shr 6;
//如果是LongTag则读取下面的TagLength
if TagLength=$3F then
begin

Move(FileBuf[CurrentPos],TagLength,Sizeof(TagLength));
Inc(CurrentPos,Sizeof(TagLength));
end;

Case TagID of
24 : begin

//是否有SWF保护设置
//如果有则将该Tag去掉,将后面的Tag搬过来覆盖掉TagID为24的部分
Move(FileBuf[CurrentPos+TagLength],FileBuf[TagPos],FileLength-(CurrentPos+TagLength)+1);
//相应的,要减去文件长度FileLength
FileLength:=FileLength-(Sizeof(TagID)+TagLength);
CurrentPos:=TagPos;
end;

14 : begin

//读取Event Sounds
Move(FileBuf[CurrentPos],SoundID,Sizeof(SoundID));
Inc(CurrentPos,Sizeof(SoundID));
tmpPos:=CurrentPos;
Move(FileBuf[CurrentPos],SoundInfo,Sizeof(SoundInfo));
Inc(CurrentPos,Sizeof(SoundInfo));
Move(FileBuf[CurrentPos],SoundSampleCount,Sizeof(SoundSampleCount));
Inc(CurrentPos,Sizeof(SoundSampleCount));
case SoundInfo shr 4 of
0,1 : s:='.WAV';
2 : s:='.MP3';
end;

l:=TagLength-Sizeof(SoundID);
//将Tag的数据部分作为声音数据存盘
AssignFile(fw,e_dir2.text+Filename+'_SOUND'+IntToStr(SoundID)+s);
ReWrite(fw,1);
BlockWrite(fw,FileBuf[tmpPos],l);
CloseFile(fw);
CurrentPos:=tmpPos+l;
end;

18 : begin

//读取Stream Sounds的数据头
//ID=18属于SoundStreamHead
//先检查前面是否已有了Stream Sounds,如果有则先存盘
if Length(Buf)<>0 then
begin

AssignFile(fw,e_dir2.text+Filename+'_StreamSound'+IntToStr(SoundCount)+SoundFile);
ReWrite(fw,1);
BlockWrite(fw,Buf[0],Length(Buf));
CloseFile(fw);
Inc(SoundCount);
end;

SetLength(Buf,0);
Move(FileBuf[CurrentPos],StreamHeadb1,Sizeof(StreamHeadb1));
Inc(CurrentPos,Sizeof(StreamHeadb1));
Move(FileBuf[CurrentPos],StreamHeadb2,Sizeof(StreamHeadb2));
Inc(CurrentPos,Sizeof(StreamHeadb2));
Move(FileBuf[CurrentPos],StreamSoundSampleCount,Sizeof(StreamSoundSampleCount));
Inc(CurrentPos,Sizeof(StreamSoundSampleCount));
//此处有1个UnKnow1数据,占16位,没有用处
Move(FileBuf[CurrentPos],UnKnow1,Sizeof(UnKnow1));
Inc(CurrentPos,Sizeof(UnKnow1));
case StreamHeadb2 shr 4 of
0,1 : SoundFile:='.WAV';
2 : SoundFile:='.MP3';
end;

end;

45 : begin

//读取Stream Sounds的数据头
//ID=45属于SoundStreamHead2
//先检查前面是否已有了Stream Sounds,如果有则先存盘
if Length(Buf)<>0 then
begin

AssignFile(fw,e_dir2.text+Filename+'_StreamSound'+IntToStr(SoundCount)+SoundFile);
ReWrite(fw,1);
BlockWrite(fw,Buf[0],Length(Buf));
CloseFile(fw);
Inc(SoundCount);
end;

SetLength(Buf,0);
Move(FileBuf[CurrentPos],StreamHeadb1,Sizeof(StreamHeadb1));
Inc(CurrentPos,Sizeof(StreamHeadb1));
Move(FileBuf[CurrentPos],StreamHeadb2,Sizeof(StreamHeadb2));
Inc(CurrentPos,Sizeof(StreamHeadb2));
Move(FileBuf[CurrentPos],StreamSoundSampleCount,Sizeof(StreamSoundSampleCount));
Inc(CurrentPos,Sizeof(StreamSoundSampleCount));
//不同于ID=18,此处没有UnKnow1数据
case StreamHeadb2 shr 4 of
0,1 : SoundFile:='.WAV';
2 : SoundFile:='.MP3';
end;

end;

19 : begin

//将每1帧(位于每1个ID=19的Tag数据中)的声音数据读取并组合在一起
//此处有1个UnKnow2数据,占32位,没有用处
Move(FileBuf[CurrentPos],UnKnow2,Sizeof(UnKnow2));
Inc(CurrentPos,Sizeof(UnKnow2));
l:=Length(Buf);
//求出缓冲区现在长度
SetLength(Buf,l+TagLength-Sizeof(Unknow2));
//将缓冲区加长
//顺序存放
Move(FileBuf[CurrentPos],Buf[l],TagLength-Sizeof(Unknow2));
Inc(CurrentPos,TagLength-Sizeof(Unknow2));
end;

0 : begin

//结尾处检查前面是否有Stream Sounds,如果有则存盘
if Length(Buf)<>0 then
begin

AssignFile(fw,e_dir2.text+Filename+'_StreamSound'+IntToStr(SoundCount)+SoundFile);
ReWrite(fw,1);
BlockWrite(fw,Buf[0],Length(Buf));
CloseFile(fw);
end;

end;

else
CurrentPos:=CurrentPos+TagLength;
end;

until TagID=0;

SetLength(FileBuf,0);
SetLength(Buf,0);


end;


showmessage ('呵呵,真的很方便,这么快就完成了!');
b_open.Caption :='选择SWF文件并提取其所含声音文件';
b_open.Enabled :=true;
Button3.Enabled :=true;

end;


procedure TMain.Button3Click(Sender: TObject);
begin

Close;
end;


procedure TMain.FormShow(Sender: TObject);
var
s : string;
begin

s:=Application.ExeName;
s:=ExtractFilePath(s);
if s[Length(s)]<>'/' then
s:=s+'/';
e_dir2.Text:=s;
end;


procedure TMain.SpeedButton1Click(Sender: TObject);
var
s : string;
info : TBROWSEINFO;
Buf : array [0..MAX_PATH] of char;
p : PItemIDList;
begin

FillChar(Buf[0],MAX_PATH+1,0);
with infodo
begin

hwndOwner:=Handle;
pidlRoot:=Nil;
pszDisplayName:=buf;
lpszTitle:='请选择设置所提取的声音文件的存盘路径';
ulFlags:=BIF_RETURNONLYFSDIRS;
lpfn:=Nil;
end;

p:=SHBrowseForFolder(info);
if Buf<>'' then
begin

SHGetPathFromIDList(p,buf);
s:=Buf;
if s[length(s)]<>'/' then
s:=s+'/';
e_dir2.text:=s;
end;

end;



end.


 
我也有此问题,还有如何提取图形
 
我试了你的程序,没问题呀,就是遇到加密的Flash6生成的swf不行,需要zlib 解码,
我也在研究swf而且也要大量swf转mp3 有空交流交流
 
zoutie兄弟:
声音格式我研究明白了
但是图像有问题:
1、是不是swf中的图形资源大多数是jpg压缩(有些是zlib压缩)
2、用definebits tag 和 jpegtables tag怎么生成jpeg
现在正在研究jpeg的结构,我qq:15330533 一般白天都在,一块研究
 
TO:delphibbs1862
有关于swf文件的ZLIB解码这块的资料吗?
 
procedure tsourcefm.getstreamsoundfile(x:integer;flag:boolean);
var f:tmemorystream;
s:string;
StreamHeadb1,StreamHeadb2:byte;
StreamSoundSampleCount:word;
unknow1:word;
len,unknow2:longword;
xname:integer;
count:integer;
begin

currentpos:=idbuf[x].pos;
xname:=x;
count:=0;
setlength(buf,0);
Move(FileBuf[CurrentPos],StreamHeadb1,Sizeof(StreamHeadb1));
Inc(CurrentPos,Sizeof(StreamHeadb1));
Move(FileBuf[CurrentPos],StreamHeadb2,Sizeof(StreamHeadb2));
Inc(CurrentPos,Sizeof(StreamHeadb2));
Move(FileBuf[CurrentPos],StreamSoundSampleCount,Sizeof(StreamSoundSampleCount));
Inc(CurrentPos,Sizeof(StreamSoundSampleCount));
if idbuf[x].id=18 then

//此处有1个UnKnow1数据,占16位,没有用处
Move(FileBuf[CurrentPos],UnKnow1,Sizeof(UnKnow1));Inc(CurrentPos,Sizeof(UnKnow1));
s:='';
case StreamHeadb2 shr 4 of
0,1 : s:='.WAV';
2 : S:='.MP3';
end;

inc(x);
repeat
if idbuf[x].id=19 then

begin

count:=count+1;
currentpos:=idbuf[x].pos;
//去掉一个32位字节的数
Move(FileBuf[CurrentPos],UnKnow2,Sizeof(UnKnow2));Inc(CurrentPos,Sizeof(UnKnow2));
len:=length(buf);
setlength(buf,idbuf[x].length+len-sizeof(unknow2));
Move(FileBuf[CurrentPos],Buf[len],idbuf[x].length-Sizeof(Unknow2));
end;

inc(x);
until (idbuf[x].id=18) or (idbuf[x].id=45) or (idbuf[x].id=0);
if flag then

begin

t.SubItems.Add(inttostr(count));
t.SubItems.add(inttostr(length(buf)));
end
else

begin

if length(buf)>0 then

begin

f:=tmemorystream.Create;
f.Size:=length(buf);
move(buf[0],f.memory^,length(buf));
path:=savepath+inttostr(idbuf[xname].id)+'_'+inttostr(xname)+'流'+s;
f.SaveToFile(path);
f.Free;
ShellExecute(application.handle,nil,pchar(path),nil,nil,SW_SHOWNORMAL);
end
else

showmessage('ID为45的声音数据为空');
if sourcefm.listview1.Selected.SubItems.Count<3 then

sourcefm.listview1.Selected.SubItems.Add(inttostr(count));
if sourcefm.listview1.Selected.SubItems.Count<4 then

sourcefm.listview1.Selected.SubItems.Add(inttostr(length(buf)));
end;

end;


procedure Tsourcefm.getsound(x:integer);
var
soundid:word;
SoundInfo:byte;
SoundSampleCount:longword;
s:string;
StreamHeadb1,StreamHeadb2:byte;
StreamSoundSampleCount:word;
unknow1:word;
begin

currentpos:=idbuf[x].pos;
s:='';
if idbuf[x].id=14 then

begin

Move(FileBuf[CurrentPos],SoundID,Sizeof(SoundID));
Inc(CurrentPos,Sizeof(SoundID));
Move(FileBuf[CurrentPos],SoundInfo,Sizeof(SoundInfo));
Inc(CurrentPos,Sizeof(SoundInfo));
Move(FileBuf[CurrentPos],SoundSampleCount,Sizeof(SoundSampleCount));
Inc(CurrentPos,Sizeof(SoundSampleCount));
case SoundInfo shr 4 of
0,1 : s:='.WAV';
2 : s:='.MP3';
end;

end
else

begin

Move(FileBuf[CurrentPos],StreamHeadb1,Sizeof(StreamHeadb1));
Inc(CurrentPos,Sizeof(StreamHeadb1));
Move(FileBuf[CurrentPos],StreamHeadb2,Sizeof(StreamHeadb2));
Inc(CurrentPos,Sizeof(StreamHeadb2));
Move(FileBuf[CurrentPos],StreamSoundSampleCount,Sizeof(StreamSoundSampleCount));
Inc(CurrentPos,Sizeof(StreamSoundSampleCount));
//此处有1个UnKnow1数据,占16位,没有用处
Move(FileBuf[CurrentPos],UnKnow1,Sizeof(UnKnow1));Inc(CurrentPos,Sizeof(UnKnow1));
case StreamHeadb2 shr 4 of
0,1 : s:='.WAV';
2 : S:='.MP3';
end;

end;


t:=listview1.Items.Add;
if (idbuf[x].id=18) or (idbuf[x].id=45) then
t.Caption:=inttostr(idbuf[x].id)+'_'+inttostr(x)+'流'+s
else

t.Caption:=inttostr(idbuf[x].id)+'_'+inttostr(x)+s;
t.SubItems.Add(inttostr(x));
t.subitems.add(inttostr(idbuf[x].id));
if idbuf[x].id=14 then

begin

t.SubItems.add('1');
t.SubItems.Add(inttostr(idbuf[x].length-2));
end;

t.ImageIndex:=0;
if idbuf[x].id<>14 then

getstreamsoundfile(x,true);
end;
 
后退
顶部