
Г-н Посол
   
Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.
Репутация: 16 Всего: 112
|
Пример использования: MergeAviWav (['1.wav', '1.avi'], 'merged.avi'); (по идее можно склеивать больше чем 2 потока: если засунуть в файл 2 или более аудиопотока, то в проигрывателях появляется возможность выбора трека (например для фильма: русская или английская озвучка); если несколько видеопотоков, то первый проигрывается в окне проигрывателя, а другие - в отдельных окнах...) Код | uses VFW;
procedure MergeAviWav (const InFiles : array of string; const OutFile : string); var pStreams : array of PAVISTREAM; i : integer; begin AVIFileInit; SetLength (pStreams, Length(InFiles)); for i := 0 to High(pStreams) do AVIStreamOpenFromFile (pStreams[i], PChar(InFiles[i]), 0, 0, OF_READ or OF_SHARE_DENY_WRITE, nil); DeleteFile (OutFile); AVISaveV (PChar(OutFile), nil, nil, Length(InFiles), pStreams[0], PAVICOMPRESSOPTIONS(nil^)); for i := 0 to High(pStreams) do AVIStreamRelease (pStreams[i]); // в случае интерфейсов этого делать не надо AVIFileExit; end;
|
Если VFW.pas нет, то можно скачать здесь: ftp://delphi-jedi.org/api/vfw.zip (но тогда надо заменить в кода PAVISTREAM на IAVISTREAM, и AVIStreamRelease делать не надо), либо прописать так: Код | const AVIFILDLL = 'AVIFIL32.DLL';
type PAVISTREAM = pointer; PAVICOMPRESSOPTIONS = pointer; procedure AVIFileInit; stdcall; external AVIFILDLL; procedure AVIFileExit; stdcall; external AVIFILDLL; function AVIStreamOpenFromFile(var ppavi: PAVISTREAM; szFile: LPCSTR; fccType: DWORD; lParam: DWORD; mode: UINT; pclsidHandler: pointer): HResult; stdcall; external AVIFILDLL name 'AVIStreamOpenFromFileA'; function AVISaveV(szFile : LPCSTR; pclsidHandler : Pointer; lpfnCallback : Pointer; nStreams : integer; var ppavi : PAVISTREAM; var plpOptions : Pointer ): HResult; stdcall; external AVIFILDLL name 'AVISaveVA'; function AVIStreamRelease(pavi: PAVISTREAM): DWORD; stdcall; external AVIFILDLL;
|
На всякий случай, покажу еще небольшую доработку - при склеивании из файлов будут изыматься все потоки, не только первые попавшиеся: Код | procedure MergeFiles (const InFiles : array of string; const OutFile : string); var pStreams : array of PAVISTREAM; stream : PAVISTREAM; FileNo, StreamNo : integer; begin AVIFileInit; FileNo := 0; SetLength (pStreams, 0); while FileNo <= High(InFiles) do begin StreamNo := 0; repeat stream := nil; AVIStreamOpenFromFile (stream, PChar(InFiles[FileNo]), 0, StreamNo, OF_READ or OF_SHARE_DENY_WRITE, nil); if stream = nil then Break; SetLength(pStreams, Length(pStreams)+1); pStreams[High(pStreams)] := stream; Inc (StreamNo); until False; Inc (FileNo); end; if Length (pStreams) > 0 then begin DeleteFile (OutFile); AVISaveV (PChar(OutFile), nil, nil, Length(pStreams), pStreams[0], PAVICOMPRESSOPTIONS(nil^)); for StreamNo := 0 to High(pStreams) do AVIStreamRelease(pStreams[StreamNo]); // в случае интерфейсов этого делать не надо! end; AVIFileExit; end; |
-------------------------------- Еще интересный вариант от Girder'а (он делал это независимо от меня, почти одновременно): Код | unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComObj; const AviDll='avifil32.dll'; ICMF_CHOOSE_ALLCOMPRESSORS=$00000008; streamtypeVIDEO=$73646976; type PAVICompressOptions=^TAVICompressOptions; TAVICompressOptions=packed record fccType:DWord; fccHandler:DWord; dwKeyFrameEvery:DWord; dwQuality:DWord; dwBytesPerSecond:DWord; dwFlags:DWord; lpFormat:Pointer; cbFormat:DWord; lpParms:Pointer; cbParms:DWord; dwInterleaveEvery:DWord; end; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; procedure AVIFileInit(); stdcall; external AviDll; procedure AVIFileExit(); stdcall; external AviDll; function AVIFileOpenA(var ppfile:DWord; szFile:PAnsiChar; mode:DWord; pclsidHandler:Pointer):DWord; stdcall; external AviDll; function AVIFileRelease(pfile: DWord):DWord; stdcall; external AviDll; function AVIFileGetStream(pfile:DWord; var ppavi:DWord; fccType:DWord; lParam:DWord):DWord; stdcall; external AviDll; function AVIStreamRelease(pavi:DWord):DWord; stdcall; external AviDll; function CreateEditableStream(var ppsEditable:DWord; psSource:DWord):DWord; stdcall; external AviDll; function AVISaveOptions(hwnd:DWord; uiFlags:DWord; nStreams:DWord; ppavi:Pointer; plpOptions:Pointer):Bool; stdcall; external AviDll; function AVISaveVA(szFile:PAnsiChar; pclsidHandler:Pointer; lpfnCallback:Pointer; nStreams:DWord; ppavi:Pointer; plpOptions:Pointer):DWord; stdcall; external AviDll; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); function GetStream(FileName:string; fccType:DWord):DWord; var _File:DWord; ws:DWord; r:DWord; begin Result:=0; if AVIFileOpenA(_File,PChar(FileName),OF_READ,nil)=0 then begin if AviFileGetStream(_File,ws,fccType,0)=0 then begin if CreateEditableStream(r,ws)=0 then Result:=r; AVIStreamRelease(ws); end; AVIFileRelease(_File); end; end; var i:DWord; _as,_vs:DWord; Streams:array[0..1] of DWord; CompressOptions:array[0..1] of PAVICompressOptions; VCO:TAVICompressOptions; begin AVIFileInit(); _vs:=GetStream('K:\8\1\cool.avi',streamtypeVIDEO); _as:=GetStream('K:\8\1\notify.wav',0); if _vs<>0 then begin Streams[0]:=_vs; Streams[1]:=_as; CompressOptions[0]:=@VCO; CompressOptions[1]:=nil; if AviSaveOptions(Handle,ICMF_CHOOSE_ALLCOMPRESSORS,1,@Streams,@CompressOptions) then begin if _as<>0 then i:=2 else i:=1; if AVISaveVA('K:\8\1\Result.avi',nil,nil,i,@Streams,@CompressOptions)=0 then ShowMessage('Типо... готово!'); end; AVIStreamRelease(_vs); end; if _as<>0 then AVIStreamRelease(_as); AviFileExit(); end; end. |
--------------------
С уважением, г-н Посол.
|