| 
| 
 | Вопрос # 2 097/ вопрос открыт / | 
 |  Здравствуйте уважаемые эксперты!
 Во время написания видео-аудио проигрывателя столкнулся с такой проблемой,как медленная обработка медиа- файлов(музыка,видео),т.е. определения времени воспроизведения файла, и у меня вопрос:
 Если кто знает напишите,как найти в медиа-файле(аудио формат,иль видео формат не важно!!) время воспроизведения видео(или аудио композиции),если сможете,то напишите хотя бы литературу,где написаны,какие байты из медиа-файла даны под информацию о времени проигрывания.
 А если предоставите код,то буду просто рад.
 А то время опредиления например 1700 файлов составляет 37 секунд,а в AIM'пе всего 5:((,хочу хоть чуть-чуть приблизится к нему)).
 
 Сразу скажу,что определяю время,через DirectShow.
 
|  |   Вопрос задал: Anatol_rus (статус: Посетитель)Вопрос отправлен: 17 ноября 2008, 22:41
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Feniks Здравствуйте, Anatol_rus!Я нашел несколько примеров в приложении:
 1. Как прочитать свойства видео файла;
 2. Информация о AVI файле, (разбор заголовка AVI);
 3. Как определить продолжительность в секундах wav файла.
 А по поводу MP3 ищите тут на сайте в вопросах и ответах. Как-то уже выкладывали информацию, как можно прочитать заголовки mp3.
 
 P.S. Желаю удачи.
 Приложение:Переключить в обычный режим  typeTDSMediaInfo = record   SurfaceDesc: TDDSurfaceDesc;   Pitch: integer;   PixelFormat: TPixelFormat;   MediaLength: Int64;   AvgTimePerFrame: Int64;   FrameCount: integer;   Width: integer;   Height: integer;   FileSize: Int64;end; function GetHugeFileSize(const FileName: string): int64;varFileHandle: hFile;beginFileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyNone);try   LARGE_INTEGER(Result).LowPart := GetFileSize(FileHandle, @LARGE_INTEGER(Result).HighPart);   if LARGE_INTEGER(Result).LowPart = $FFFFFFFF then     Win32Check(GetLastError = NO_ERROR);finally   FileClose(FileHandle);end;end; function GetMediaInfo(FileName: WideString): TDSMediaInfo;varDirectDraw: IDirectDraw;AMStream: IAMMultiMediaStream;MMStream: IMultiMediaStream;PrimaryVidStream: IMediaStream;DDStream: IDirectDrawMediaStream;GraphBuilder: IGraphBuilder;MediaSeeking: IMediaSeeking;TimeStart, TimeStop: Int64;DesiredSurface: TDDSurfaceDesc;DDSurface: IDirectDrawSurface;beginif FileName = '' then   raise Exception.Create('No File Name Specified');OleCheck(DirectDrawCreate(nil, DirectDraw, nil));DirectDraw.SetCooperativeLevel(GetDesktopWindow(), DDSCL_NORMAL);Result.FileSize := GetHugeFileSize(FileName);AMStream := IAMMultiMediaStream(CreateComObject(CLSID_AMMultiMediaStream));OleCheck(AMStream.Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, nil));OleCheck(AMStream.AddMediaStream(DirectDraw, MSPID_PrimaryVideo, 0, IMediaStream(nil^)));OleCheck(AMStream.OpenFile(PWideChar(FileName), AMMSF_NOCLOCK));AMStream.GetFilterGraph(GraphBuilder);MediaSeeking := GraphBuilder as IMediaSeeking;MediaSeeking.GetDuration(Result.MediaLength);MMStream := AMStream as IMultiMediaStream;OleCheck(MMStream.GetMediaStream(MSPID_PrimaryVideo, PrimaryVidStream));DDStream := PrimaryVidStream as IDirectDrawMediaStream;DDStream.GetTimePerFrame(Result.AvgTimePerFrame);{Result.FrameCount := Result.MediaLength div Result.AvgTimePerFrame;}{ TODO : Test for better accuracy }Result.FrameCount := Round(Result.MediaLength / Result.AvgTimePerFrame);Result.MediaLength := Result.FrameCount * Result.AvgTimePerFrame;ZeroMemory(@DesiredSurface, SizeOf(DesiredSurface));DesiredSurface.dwSize := Sizeof(DesiredSurface);OleCheck(DDStream.GetFormat(TDDSurfaceDesc(nil^), IDirectDrawPalette(nil^),   DesiredSurface, DWord(nil^)));Result.SurfaceDesc := DesiredSurface;DesiredSurface.ddsCaps.dwCaps := DesiredSurface.ddsCaps.dwCaps or   DDSCAPS_OFFSCREENPLAIN or DDSCAPS_SYSTEMMEMORY;DesiredSurface.dwFlags := DesiredSurface.dwFlags or DDSD_CAPS or DDSD_PIXELFORMAT;{Create a surface here to get vital statistics}OleCheck(DirectDraw.CreateSurface(DesiredSurface, DDSurface, nil));OleCheck(DDSurface.GetSurfaceDesc(DesiredSurface));Result.Pitch := DesiredSurface.lPitch;if DesiredSurface.ddpfPixelFormat.dwRGBBitCount = 24 then   Result.PixelFormat := pf24bitelse if DesiredSurface.ddpfPixelFormat.dwRGBBitCount = 32 then   Result.PixelFormat := pf32bit;Result.Width := DesiredSurface.dwWidth;Result.Height := DesiredSurface.dwHeight;end;  unit Unit1; interface usesWindows, Messages, SysUtils, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; TypeTForm1 = class(TForm)   Memo1: TMemo;   OpenDialog1: TOpenDialog;   Button1: TButton;   procedure Button1Click(Sender: TObject);Public   procedure ReadAviInfo(FileName: String);End; varForm1: TForm1; implementation {$R *.dfm} procedure TForm1.ReadAviInfo(FileName: String);var   Aviheadersize: Integer;Vheadersize: Integer;Aviheaderstart: Integer;Vheaderstart: Integer;Aheaderstart: Integer;Astrhsize: Integer;  TempTest: String[5];TempSize: Integer;TempVcodec: String[5];TempAcodec: Integer;TempMicrosec: Integer;TempLengthInFrames: Integer;TempAchannels: Integer;TempAsamplerate: Integer;TempAbitrate: Integer;  Size: Double;Length: String;Vcodec: String;Vbitrate: Double;VWidth: Integer;VHeight: Integer;Fps: Double; LengthInSec: Double;Acodec: String;Abitrate: String;begin iFileHandle := FileOpen(FileName, fmOpenRead);  FileSeek(iFileHandle, 7, 0);FileRead(iFileHandle, TempTest, 5);If copy(TempTest, 0, 4) <> 'AVI ' thenbegin   MessageDlg('Could not open ' + FileName + ' because it is not a valid video file', mtError,
[mbOk], 0);   Exit;End;  FileSeek(iFileHandle,4,0);FileRead(iFileHandle, TempSize, 4);  FileSeek(iFileHandle,28,0);FileRead(iFileHandle, Aviheadersize, 4);  Aviheaderstart := 32;  FileSeek(iFileHandle,Aviheaderstart,0);FileRead(iFileHandle, TempMicrosec, 4);  FileSeek(iFileHandle,Aviheaderstart + 16,0);FileRead(iFileHandle, TempLengthInFrames, 4);  FileSeek(iFileHandle,Aviheaderstart + 32,0);FileRead(iFileHandle, VWidth, 4);  FileSeek(iFileHandle,Aviheaderstart + 36,0);FileRead(iFileHandle, VHeight, 4); FileSeek(iFileHandle,Aviheaderstart + Aviheadersize + 4,0);FileRead(iFileHandle, Vheadersize, 4); Vheaderstart := Aviheaderstart + Aviheadersize + 20;  FileSeek(iFileHandle,Vheaderstart + 3,0);FileRead(iFileHandle, TempVCodec, 5); Aheaderstart := Vheaderstart + Vheadersize + 8; FileSeek(iFileHandle,Aheaderstart - 4,0);FileRead(iFileHandle, Astrhsize, 5); // Audio codecFileSeek(iFileHandle,Aheaderstart + Astrhsize + 8,0);FileRead(iFileHandle, TempACodec, 2);  FileSeek(iFileHandle,Aheaderstart + Astrhsize + 10,0);FileRead(iFileHandle, TempAchannels, 2); // Audio samplerateFileSeek(iFileHandle,Aheaderstart + Astrhsize + 12,0);FileRead(iFileHandle, TempAsamplerate, 4); // Audio bitrateFileSeek(iFileHandle,Aheaderstart + Astrhsize + 16,0);FileRead(iFileHandle, TempAbitrate, 4);  FileClose(iFileHandle);  Vcodec := copy(TempVcodec, 0, 4);If Vcodec = 'div2' then Vcodec := 'MS MPEG4 v2'Else If Vcodec = 'DIV2' then Vcodec := 'MS MPEG4 v2'Else If Vcodec = 'div3' then Vcodec := 'DivX;-) MPEG4 v3'Else If Vcodec = 'DIV3' then Vcodec := 'DivX;-) MPEG4 v3'Else If Vcodec = 'div4' then Vcodec := 'DivX;-) MPEG4 v4'Else If Vcodec = 'DIV4' then Vcodec := 'DivX;-) MPEG4 v4'Else If Vcodec = 'div5' then Vcodec := 'DivX;-) MPEG4 v5'Else If Vcodec = 'DIV5' then Vcodec := 'DivX;-) MPEG4 v5'Else If Vcodec = 'divx' then Vcodec := 'DivX 4'Else If Vcodec = 'mp43' then Vcodec := 'Microcrap MPEG4 v3';  Case TempAcodec of   0: Acodec := 'PCM';   1: Acodec := 'PCM';   85: Acodec := 'MPEG Layer 3';   353: Acodec := 'DivX;-) Audio';   8192: Acodec := 'AC3-Digital';Else   Acodec := 'Unknown (' + IntToStr(TempAcodec) + ')';End; Case (Trunc(TempAbitrate / 1024 * 8)) of   246..260: Abitrate := '128 Kbit/s';   216..228: Abitrate := '128 Kbit/s';   187..196: Abitrate := '128 Kbit/s';   156..164: Abitrate := '128 Kbit/s';   124..132: Abitrate := '128 Kbit/s';   108..116: Abitrate := '128 Kbit/s';   92..100: Abitrate := '128 Kbit/s';   60..68: Abitrate := '128 Kbit/s';Else   Abitrate := FormatFloat('# Kbit/s', TempAbitrate / 1024 * 8);End;  Size := TempSize / 1024 / 1024;Fps := 1000000 / TempMicrosec; // FPSLengthInSec := TempLengthInFrames / fps; // Length In secondsLength := FormatFloat('# min', Int(LengthInSec / 60)) + FormatFloat(' # sec',   Round(LengthInSec - (Int(LengthInSec / 60) * 60)));Vbitrate := (TempSize / LengthInSec - TempABitrate) / 1024 * 8;  Memo1.Lines.Add('AVI INFORMATION');Memo1.lines.Add('Size: ' + FormatFloat('#.## MB',Size));Memo1.Lines.Add('Length: ' + Length);Memo1.Lines.Add('');Memo1.Lines.Add('VIDEO INFORMATION');Memo1.Lines.Add('Codec: ' + Vcodec);Memo1.Lines.Add('Bitrate: ' + FormatFloat('# Kbit/s', Vbitrate));Memo1.lines.Add('Width: ' + IntToStr(VWidth) + ' px');Memo1.lines.Add('Height: ' + IntToStr(VHeight) + ' px');Memo1.Lines.Add('FPS: ' + FormatFloat('#.##', fps));Memo1.Lines.Add('');Memo1.Lines.Add('AUDIO INFORMATION');Memo1.Lines.Add('Codec: ' + Acodec);Memo1.Lines.Add('Bitrate: ' + Abitrate);End; procedure TForm1.Button1Click(Sender: TObject);beginIf OpenDialog1.Execute Then ReadAviInfo(OpenDialog1.FileName);End; end.   -------------uses MPlayer, MMsystem;  type EMyMCIException = class(Exception); TWavHeader = record    Marker1: array[0..3] of Char;    BytesFollowing: Longint;    Marker2: array[0..3] of Char;    Marker3: array[0..3] of Char;    Fixed1: Longint;    FormatTag: Word;    Channels: Word;    SampleRate: Longint;    BytesPerSecond: Longint;    BytesPerSample: Word;    BitsPerSample: Word;    Marker4: array[0..3] of Char;    DataBytes: Longint; end;  procedure TForm1.Button1Click(Sender: TObject); var Header: TWavHeader; begin with TFileStream.Create('C:SomeFile.wav', fmOpenRead) do    try      ReadBuffer(Header, SizeOf(Header));    finally      Free;    end; ShowMessage(FloatToStr((Int64(1000) * header.DataBytes div header.BytesPerSecond) / 1000)); end;    -------------function GetWaveLength(WaveFile: string): Double;var  groupID: array[0..3] of char;  riffType: array[0..3] of char;  BytesPerSec: Integer;  Stream: TFileStream;  dataSize: Integer;// chunk seeking function,// -1 means: chunk not found function GotoChunk(ID: string): Integer;var     chunkID: array[0..3] of char;     chunkSize: Integer;begin     Result := -1;    with Stream do       begin            // index of first chunk         Position := 12;       repeat            // read next chunk         Read(chunkID, 4);         Read(chunkSize, 4);          if chunkID <> ID then            // skip chunk        Position := Position + chunkSize;         until(chunkID = ID) or (Position >= Size);         if chunkID = ID then              // chunk found,            // return chunk size           Result := chunkSize;       end;end; begin  Result := -1;  Stream := TFileStream.Create(WaveFile, fmOpenRead or fmShareDenyNone);  with Stream do       try         Read(groupID, 4);      Position := Position + 4; // skip four bytes (file size)      Read(riffType, 4);       if(groupID = 'RIFF') and (riffType = 'WAVE') then          begin             // search for format chunk         if GotoChunk('fmt') <> -1 then             begin               // found it            Position := Position + 8;            Read(BytesPerSec, 4);               //search for data chunk              dataSize := GotoChunk('data');               if dataSize <> -1 then                    // found it                Result := dataSize / BytesPerSec               end           end       finally         Free;    end;end; function SecondsToTimeStr(RemainingSeconds: Integer): string;var  Hours, Minutes, Seconds: Integer;  HourString, MinuteString, SecondString: string;begin   // Calculate Minutes  Seconds := RemainingSeconds mod 60;  Minutes := RemainingSeconds div 60;  Hours := Minutes div 60;  Minutes := Minutes - (Hours * 60);   if Hours < 10 then      HourString := '0' + IntToStr(Hours) + ':'    else      HourString := IntToStr(Hours) + ':';   if Minutes < 10 then       MinuteString := '0' + IntToStr(Minutes) + ':'     else       MinuteString := IntToStr(Minutes) + ':';   if Seconds < 10 then       SecondString := '0' + IntToStr(Seconds)     else       SecondString := IntToStr(Seconds);  Result := HourString + MinuteString + SecondString;end;procedure TForm1.Button1Click(Sender: TObject);var Seconds: Integer;begin  Seconds := Trunc(GetWaveLength(Edit1.Text));   //gets only the Integer part of the length  Label1.Caption := SecondsToTimeStr(Seconds);end;procedure TForm1.Button1Click(Sender: TObject);begin  Label1.Caption := SecondsToTimeStr(Trunc(GetWaveLength(Edit1.Text)));end;  -------------usesMPlayer, MMsystem; typeEMyMCIException = class(Exception);TWavHeader = record   Marker1: array[0..3] of Char;   BytesFollowing: Longint;   Marker2: array[0..3] of Char;   Marker3: array[0..3] of Char;   Fixed1: Longint;   FormatTag: Word;   Channels: Word;   SampleRate: Longint;   BytesPerSecond: Longint;   BytesPerSample: Word;   BitsPerSample: Word;   Marker4: array[0..3] of Char;   DataBytes: Longint;end; procedure TForm1.Button1Click(Sender: TObject);varHeader: TWavHeader;beginwith TFileStream.Create('C:SomeFile.wav', fmOpenRead) do   try     ReadBuffer(Header, SizeOf(Header));   finally     Free;   end;ShowMessage(FloatToStr((Int64(1000) * header.DataBytes div header.BytesPerSecond) / 1000));end;
|  | Ответ отправил: Feniks (статус: Бакалавр)Время отправки: 18 ноября 2008, 09:54
 
 |  
 Мини-форум вопросаВсего сообщений: 1; последнее сообщение — 18 ноября 2008, 09:45; участников в обсуждении: 1. 
|   | Вадим К (статус: Академик), 18 ноября 2008, 09:45 [#1]:Вообще то один формат другому разница и универсального метода нет. Конечно, можно воспользоваться прослойкой, как вы, но она часто добавляет сколько тормозов... AIMP воспроизводит свои файлы через bass.dll. Поищите описание этой длл и посмотрите на её возможности, может быть хватит.
 Вытянуть размер с mp3 файла не сложно. Но не всякий файл, который имеет расширения mp3 им есть. плееры давно научились определять истинное содержимое по заголовку.
 Галочка "подтверждения прочтения" - вселенское зло. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |