locked
Finding Length of an Real Media Audio File RRS feed

  • Question

  • Hi,

    I need to find out the length (i.e. HH:MM:SS) of a rm (Real Media) Audio File from my application which I made in Visual Basic 6.0. I don't need to play it or record it, just find out the length of the file.

    Please let me know how this can be possible.

    Thanks

    Amad

    Friday, December 1, 2006 9:59 AM

Answers

  • The web link given details the structure of a real media file.

    To use it you would open the real media file and check the header for its version which will let you know the rest of the header format. Following the header is a series of "chunks" which are detailed. The chunk you want is the one below

    File properties header (PROP)

    This chunk contains some information about the general properties of a RealMedia file. Only one PROP chunk can be present in a file.

    A PROP chunk has the following format

    dword Chunk type ('PROP')
    dword Chunk size (typically 0x32)
    word Chunk version (always 0, for every known file)
    dword Maximum bit rate
    dword Average bit rate
    dword Size of largest data packet
    dword Average size of data packet
    dword Number of data packets in the file
    dword File duration in ms
    dword Suggested number of ms to buffer before starting playback
    dword Offset of the first INDX chunk form the start of the file
    dword Offset of the first DATA chunk form the start of the file
    word Number of streams in the file
    word Flags (bitfield, see below)

    As you can see this chunk gives the file duration in milliseconds as a dword (int16).

    Reading files is quite easy in VB, for this kind of file you will need to open the file in binary.

    I am assuming it is not an .RA file that only contains a string to an internet link, and you will need to provide the file name.

    The PROP chunk follows the header so you can do the following but really you should verify that the chunk after the header is the PROP. This is extremely quick and dirty example so you can refine it to your needs.

    Dim myHandle As FileStream
    Dim myReader As BinaryReader
    DIM Duration As Int16

    <VBFixedString(4)> public id As String

    myHandle = New FileStream(<FILE NAME>, FileMode.Open)
    myReader = New BinaryReader(myHandle)

    ' Read header, only interested in the id part

    id = myReader.ReadChars(4)
    myReader.ReadBytes(16)

    'if it is a header read off bytes to position of duration

    If id = ".RMF" Then
       myReader.ReadBytes(26)
       Duration = myReader.ReadInt16

    ' you can then divide duration by 60,000 to get minutes...

    End If

    myReader.Close()
    myHandle.Close()
    myHandle.Dispose()

    Friday, December 1, 2006 1:07 PM

All replies

  • A quick search on Google with the words "real media audio file header" produced:


    http://wiki.multimedia.cx/index.php?title=RealMedia

    Friday, December 1, 2006 11:39 AM
  • Thanks but this links does not contain any information on how to read the length of the .rm file from Visual Basic. Please note that I require to find out the length of the audio/video file and not the size of the file.

    Also how can I read this file header from Visual Basic. Is it possible to do so ?

    Thanks

    Amad

     

    Friday, December 1, 2006 12:15 PM
  • you can read any file length using the System.IO.FileInfo class, if you are referring to the file size.

    http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.aspx

    http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.length.aspx

     

    Friday, December 1, 2006 12:54 PM
    Moderator
  • The web link given details the structure of a real media file.

    To use it you would open the real media file and check the header for its version which will let you know the rest of the header format. Following the header is a series of "chunks" which are detailed. The chunk you want is the one below

    File properties header (PROP)

    This chunk contains some information about the general properties of a RealMedia file. Only one PROP chunk can be present in a file.

    A PROP chunk has the following format

    dword Chunk type ('PROP')
    dword Chunk size (typically 0x32)
    word Chunk version (always 0, for every known file)
    dword Maximum bit rate
    dword Average bit rate
    dword Size of largest data packet
    dword Average size of data packet
    dword Number of data packets in the file
    dword File duration in ms
    dword Suggested number of ms to buffer before starting playback
    dword Offset of the first INDX chunk form the start of the file
    dword Offset of the first DATA chunk form the start of the file
    word Number of streams in the file
    word Flags (bitfield, see below)

    As you can see this chunk gives the file duration in milliseconds as a dword (int16).

    Reading files is quite easy in VB, for this kind of file you will need to open the file in binary.

    I am assuming it is not an .RA file that only contains a string to an internet link, and you will need to provide the file name.

    The PROP chunk follows the header so you can do the following but really you should verify that the chunk after the header is the PROP. This is extremely quick and dirty example so you can refine it to your needs.

    Dim myHandle As FileStream
    Dim myReader As BinaryReader
    DIM Duration As Int16

    <VBFixedString(4)> public id As String

    myHandle = New FileStream(<FILE NAME>, FileMode.Open)
    myReader = New BinaryReader(myHandle)

    ' Read header, only interested in the id part

    id = myReader.ReadChars(4)
    myReader.ReadBytes(16)

    'if it is a header read off bytes to position of duration

    If id = ".RMF" Then
       myReader.ReadBytes(26)
       Duration = myReader.ReadInt16

    ' you can then divide duration by 60,000 to get minutes...

    End If

    myReader.Close()
    myHandle.Close()
    myHandle.Dispose()

    Friday, December 1, 2006 1:07 PM
  • Rabtok,

    This was a good help, but I am still not getting the desired results. Following is the code for my application in VB 6. Please also note that I tried this in VB .Net and in the Immediate window copy and pasted the contents of the file through myreader.ReadChars(100), one by one, and found out that the file was .ra5 and also .rmf. So I think I must get the correct information. Shouldn't I ?

    Here is my code. Comments explain the results for some of the actions.

    Private Sub rmLength()
        Dim file_name As String
        Dim file_length As Long
        Dim fnum As Integer
        Dim bytes() As Byte
        Dim txt As String
        Dim txt2 As String
        Dim i As Integer
       
        file_name = "c:\auProject\AudioFile.rm"
       
        fnum = FreeFile

        txt = Space$(4)
        Open file_name For Binary As #fnum
        Get #fnum, 1, txt
        Close fnum
       
        MsgBox txt ' this displays .rmf
       
       
        ' The program starts to read from Byte # 1, till 4 characters, since
        ' the length of '.rmf' is 4.
       
        ' Now you said that after 46 bytes i.e. 4 for .rmf and then 16 more
        ' and then 26 more, it would contain the file duration information
        
        Open file_name For Binary As #fnum
        Get #fnum, 47, i
        Close fnum
       
        MsgBox i 'this returns 18969
       
        ' 18969/60000 becomes less than a minute. The file duration is just
        ' around 13 minutes. So this is not correct. 
       
    End Sub

     

    Please help I am already having sleepless nights over this.


    Thanks

    Amad

     

    Tuesday, December 5, 2006 12:20 PM
  • As I said it is just an example to help you work it out. I do not have a RM file to play with in any format so I can not tinker till I get it, but that is where most of the fun of programming is in tackling these things.

    Also I have to hold my hand up to making a small mistake it is int32 not int16...sigh!, apologise.

    You can however see from the header file that the bytes following the header marker give the size of the header block, which might be different for .RA5 format vs .RMF format.

    To deal with this you would read the size into an int32 then subtract 8 (4 for the header name".RMF" and 4 for the int32 size) this would give you the remainder of the header size, dummy read it and that would put you at the beginning of the next chunk, read its four byte header and verify it is a PROP, if not read its size, subtract 8 and dummy read to the next chunk...until you get PROP...then read out to the duration.

    If Real change the headers format for version 5 they might also change the PROP format, but this is the world of internet and the information on the header formats is out there, just apply the above logic to locate your information based on where you know Duration to be in the chunk, if it is different for .RA5 you know it is a .RA5 format already from the first header so you can get the information on the PROP chunk and read to a different offset if you want to.

    Example:

    Dim myHandle As FileStream
    Dim myReader As BinaryReader
    DIM Duration As Int32
    DIM HdrSize as Int32

    <VBFixedString(4)> public id As String

    myHandle = New FileStream(<FILE NAME>, FileMode.Open)
    myReader = New BinaryReader(myHandle)

    ' Read header, only interested in the id part

    id = myReader.ReadChars(4)
    HdrSize = myReader.ReadInt32 - 8

    myReader.ReadBytes(HdrSize)

    'if it is a header read off bytes to position of duration

    If id = ".RMF" Then

       id = myReader.ReadChars(4)

    If id="PROP" Then
       myReader.ReadBytes(26)
       Duration = myReader.ReadInt32
    End If 

    ' you can then divide duration by 60,000 to get minutes...

    End If

    myReader.Close()
    myHandle.Close()
    myHandle.Dispose()


    This is a bare bones example you would put a loop in to find PROP in case it is not the chunk after the header.

    Tuesday, December 5, 2006 1:55 PM
  • I have found the chunk PROP. It starts from the 19th byte. I found that through the code

        For cnt = 1 To 10000
            Open file_name For Binary As #fnum
            Get #fnum, cnt, str
            Close fnum

            If str = "PROP" Then
                MsgBox cnt
                Exit Sub
            End If


        Next

    Please note that through cnt I am reading each byte.

    Now comes the MAIN problem. After finding the PROP chunk;

    I add 4 bytes for each 'dword' and 2 bytes for each 'word'. Is it right, since I don't know how much length in bytes is occupied by dword and word respectively.

    Adding in such a way I come to the conclusion that the File Duration must be on the 49th byte. Now having said that I don't know that the file duration can be retrieved by which data type.

    I tried String with 4 spaces it returned blank.
    I tried integer it returned 3840
    I tried long it returned -926216448

    None of them when divided by 60,000 gives 13 minutes which is the length of my file.

    Can you please look into this, I tried searching the internet for any new format header in which rm files might be available, but couldn't find any.

    Thanks

    Amad


     

    Tuesday, December 5, 2006 6:15 PM
  •  

    VB6 Questions are off topic in these forums.

    Wednesday, December 6, 2006 1:29 AM
  • You need to be able to read a 32 bit (4 byte) integer in its native format, it is not stored as a string it is stored in binary. I do not know how VB6 does this, I presume there is a help file with VB6 that you can scour for how to read a 32 bit int, I suspect that a long is a 32 bit int but once again I do not know VB6 and its variable types.


    Wednesday, December 6, 2006 8:47 AM
  • I have switched to Vb.NET. I am using the following code and in the remarks I have put in the values which are being returned.

            Dim Duration As Int32

            Dim myHandle As FileStream
            Dim myReader As BinaryReader

            myHandle = New FileStream("c:\auProject\AudioFile.rm", FileMode.Open)
            myReader = New BinaryReader(myHandle)

            id = myReader.ReadChars(4)
            HdrSize = myReader.ReadInt32

            myReader.ReadBytes(10)
            id = myReader.ReadChars(4) 'PROP
            Duration = myReader.ReadInt32 'chunk size 838860800
            Duration = myReader.ReadInt32 ' chunk version. returns 0
            Duration = myReader.ReadInt32 ' maximum bit rate 32830
            Duration = myReader.ReadInt32 ' average bit rate 32830
            Duration = myReader.ReadInt32 ' size of largest data packet 16385
            Duration = myReader.ReadInt32 ' Average size of data packet 16385
            Duration = myReader.ReadInt32 ' Number of data packets in the file. 251677209
            Duration = myReader.ReadInt32 ' File Duration in ms 51403
            Duration = myReader.ReadInt32 ' Suggested number of ms to  buffer before starting playback 536920067
            Duration = myReader.ReadInt32 ' Offset of the first INDX chunk form the start of the file 62926
            Duration = myReader.ReadInt32 ' Offset of the first DATA chunk form the start of the file 33614594
            Duration = myReader.ReadInt32 ' Number of streams in the file 1145899264
            Duration = myReader.ReadInt32  ' Flags (bitfield, see below 21072

    Now as you can see that this the values being returned are not correctly depicting the value which the document says resides in them. I think the issue is that we are not using the correct data type to place the value into. Anymore inputs ?

     

    Wednesday, December 6, 2006 11:06 AM
  • I do not have a file to work from so can not fully help, however a dword is 32 bit a word is 16 bit, the version variable in PROP is a word not a dword so you will change the offset of the read after you have read the version and be out by one byte from there forward.


    Wednesday, December 6, 2006 1:14 PM