Page 1 sur 2

Créer vos videos AVI avec de l'audio.

Publié : dim. 29/mai/2005 14:43
par nico
Sur le Forum Anglais, une personne avait commencé une traduction d'un code VB pour créer ses vidéos AVI mais qui ne marchait pas. J'avais bien essayé à l'époque mais je n'y arrivais pas car je ne savais pas comment était codé un fichier BMP.
Maintenant que je sais, je m'y suis remis et voici un exemple de code.

C'est cool, non! :D

Code : Tout sélectionner

; Code de Nico
;mis en purebasic 4.10 par Dobro
#streamtypeVIDEO = $73646976

#Lib = 0

Structure bitmap24
  bmiHeader.BITMAPINFOHEADER
EndStructure

Structure AVISTREAMINFO
  fccType.l
  fccHandler.l
  dwFlags.l
  dwCaps.l
  wPriority.w
  wLanguage.w
  dwScale.l
  dwRate.l
  dwStart.l
  dwLength.l
  dwInitialFrames.l
  dwSuggestedBufferSize.l
  dwQuality.l
  dwSampleSize.l
  rcFrame.RECT
  dwEditCount.l
  dwFormatChangeCount.l
  szName.b[64]
EndStructure

Structure AVICOMPRESSOPTIONS
  fccType.l
  fccHandler.l
  dwKeyFrameEvery.l
  dwQuality.l
  dwBytesPerSecond.l
  dwFlags.l
  *lpFormat.l
  cbFormat.l
  *lpParms.l
  cbParms.l
  dwInterleaveEvery.l
EndStructure

NewList bitmap.s()
NewList memoire.l()

Debug SizeOf(bitmap24)
Debug (SizeOf(BITMAPFILEHEADER))

Fichier.s = OpenFileRequester("Sélection multiple des Fichiers Bitmaps", "", "Fichiers BMP|*.bmp", 0, #PB_Requester_MultiSelection)
If Fichier
  Debug  Fichier
  AddElement(bitmap())
  bitmap()= Fichier
  Repeat
    Fichier = NextSelectedFileName()
    If Fichier
      AddElement(bitmap())
      bitmap()= Fichier
      Debug Fichier
    EndIf
  Until Fichier = ""
EndIf

ForEach bitmap()
  If ReadFile(0, bitmap())
    Debug Lof(0)
    CallDebugger
    FileSeek(0,SizeOf(BITMAPFILEHEADER))
    bmi.bitmap24
    
    ReadData(0,@bmi, SizeOf(bitmap24))
    ; Debug "---------------------------------"
    ; Debug bmi\bmiHeader\biSize ;40 c'est la taille de la structure
    ; Debug bmi\bmiHeader\biWidth
    ; Debug bmi\bmiHeader\biHeight
    ; Debug bmi\bmiHeader\biPlanes
    ; Debug bmi\bmiHeader\biBitCount
    ; Debug bmi\bmiHeader\biCompression
    ; Debug bmi\bmiHeader\bisizeimage
    ; Debug bmi\bmiHeader\biXPelsPerMeter
    ; Debug bmi\bmiHeader\biYPelsPerMeter
    ; Debug bmi\bmiHeader\biClrUsed
    ; Debug bmi\bmiHeader\biClrImportant
    ; Debug "---------------------------------"   
    If  bmi\bmiHeader\biWidth
      If  bmi\bmiHeader\biHeight
        If  bmi\bmiHeader\biBitCount=24
          If  bmi\bmiHeader\biSizeImage=0
            bmi\bmiHeader\biSizeImage=Lof(0)-54
          EndIf
          FileSeek(0,54)
          AddElement(memoire())
          memoire() =GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT, bmi\bmiHeader\biSizeImage)
          ReadData(0,memoire(), bmi\bmiHeader\biSizeImage)
        EndIf
      EndIf
    EndIf
    
    CloseFile(0)
  EndIf
Next
 
If OpenLibrary  ( #Lib , "AVIFIL32.DLL")
  CallFunction ( #Lib,  "AVIFileInit" )
  avifile.s = SaveFileRequester ( "Nom du fichier Avi à enregistrer", "", "Video|*.avi", 0 )
  If GetExtensionPart(avifile)=""
    avifile=avifile+".avi"
  EndIf
  Debug avifile
  
  If CallFunction( #Lib, "AVIFileOpen", @pAVIFile.IAVIFILE, @avifile, (#OF_WRITE | #OF_CREATE), 0 )=0
    strhdr.AVISTREAMINFO
    strhdr\fccType                = #streamtypeVIDEO
    strhdr\fccHandler             = 0
    strhdr\dwScale                = 1
    strhdr\dwRate                 = 4
    strhdr\dwSuggestedBufferSize  = bmi\bmiHeader\biSize
    
    If SetRect_(@strhdr\rcFrame, 0, 0, bmi\bmiHeader\biWidth, bmi\bmiHeader\biHeight) <>0
      If CallFunction( #Lib, "AVIFileCreateStream", pAVIFile, @pAVIStream, @strhdr) =0
        opts.AVICOMPRESSOPTIONS
        Dim aopts(0)
        aopts(0)=@opts
        
        #ICMF_CHOOSE_KEYFRAME=1
        #ICMF_CHOOSE_DATARATE=2
        #AVIERR_OK=0
        #AVIIF_KEYFRAME=$10
        If CallFunction( #Lib, "AVISaveOptions", 0, #ICMF_CHOOSE_KEYFRAME | #ICMF_CHOOSE_DATARATE, 1, @pAVIStream, @aopts(0)) =1
          If CallFunction( #Lib, "AVIMakeCompressedStream", @pAVICompressed, pAVIStream, aopts(0), 0)=#AVIERR_OK
            If CallFunction( #Lib, "AVIStreamSetFormat", pAVICompressed, 0, @bmi, SizeOf(bitmap24)) =0
              ForEach memoire()
                If memoire()
                  If CallFunction( #Lib, "AVIStreamWrite", pAVICompressed, index, 1,  memoire() , bmi\bmiHeader\biSizeImage, #AVIIF_KEYFRAME, 0,0) =0
                    index=index+1
                  EndIf 
                EndIf
              Next
            EndIf
            CallFunction( #Lib, "AVIStreamRelease", pAVICompressed)
          EndIf
        EndIf
        CallFunction( #Lib, "AVIStreamRelease", pAVIStream )
      EndIf
    EndIf
    CallFunction( #Lib, "AVIFileRelease", pAVIFile)
  EndIf
  CallFunction( #Lib, "AVIFileExit" )
  CloseLibrary( #Lib )
  
  ForEach memoire()
    GlobalFree_(memoire())
  Next
  MessageRequester("Info","Nombre de Frames enregistrées: "+Str(index))
EndIf 

 

Publié : dim. 29/mai/2005 23:13
par djes
Bravo! C'est quand on arrive à résoudre d'anciens problèmes qu'on voit à quel point on progresse! Bonheur, hein? Toute le plaisir de la prog! ;)
(en plus c'était pas simple!!!)

Publié : lun. 30/mai/2005 7:02
par KarLKoX
Pas mal du tout, ca pourra servir à pas mal de personnes.
Bravo :)

Publié : lun. 30/mai/2005 12:21
par nico
Merci. :D

L'autre intérêt de ce code est de pouvoir créer des avi dynamiques et les visionner grâce à une fenêtre avec la classe SysAnimate32.

Mais pour cela, il faut modifier le code car cette classe ne peut visionner des vidéos qu'au format huit bits.

Voici les changements à opérer:

Code : Tout sélectionner

;Modifier cette structure 
Structure bitmap24 
  bmiHeader.BITMAPINFOHEADER 
EndStructure 

;par celle-ci:
Structure bitmap256 ;structure pour une image codée sur 8 bits
  bmiHeader.BITMAPINFOHEADER
  bmiColors.RGBQUAD[256]
EndStructure


;évidemment remplacer
bmi.bitmap24 par bmi.bitmap256

;et remplacé tous les
SizeOf(bitmap24) par SizeOf(bitmap256)


;Aussi remplacer
FileSeek(54) par FileSeek(1078)

; et enfin remplacer
bmi\bmiHeader\biBitCount=24 par bmi\bmiHeader\biBitCount=8

[edit] 
J'allais oublié remplacer
bmi\bmiHeader\bisizeimage=Lof()-54 par bmi\bmiHeader\bisizeimage=Lof()-1078

Bien entendu les images pour créer l'avi devront être au format 8 bits et non 24 bits

Par contre pour la transparence, cela fonctionne bien sous XP mais pas sur 98! ily a certainement une modification à faire mais laquelle?

Ainsi on peut créer facilement des animations sur des boutons par exemple!

Publié : lun. 30/mai/2005 19:11
par erix14
Bravo Nico,
ce qui serait bien c'est qu'on puisse inclure du son dans la vidéo. :D
Ça m'ouvrirait de nouveaux horizons pour des futurs programmes... :mrgreen:

Publié : mar. 31/mai/2005 12:09
par nico
Pour la transparence j'ai trouvé ce qu'il fallait modifié mais pas possible de le faire lors de la création?

C'est pas grave, il faut ré-ouvrir le fichier et modifier un bit:

Code : Tout sélectionner

  ;/ pour la transparence
  If OpenFile(0,avifile)
    FileSeek(205)
    WriteByte(1)
    CloseFile(0)
    MessageRequester("Info","Transparence Ok")
  EndIf 



:)

Publié : mar. 31/mai/2005 18:10
par nico
Un fichier Zip contenant un Exe pour donner un exemple de ce qu'on peut faire:

http://home.tele2.fr/purebasic/Animate.zip

Publié : mer. 01/juin/2005 22:25
par nico
erix14 a écrit :Bravo Nico,
ce qui serait bien c'est qu'on puisse inclure du son dans la vidéo. :D
Ça m'ouvrirait de nouveaux horizons pour des futurs programmes... :mrgreen:
J'ai pu trouver une procédure pour inclure du son au format Wave, je dois dire que je me suis un peu forcé la main pour te satisfaire; faudra pas m'en demander plus. :lol:

Dès que c'est en forme, je poste!

Publié : jeu. 02/juin/2005 10:12
par Dr. Dri
génial ton exe d'exemple ^^
seul hic, quand je bouge la fenetre l'animation se fige
pour la faire repartir je dois changer de couleur...

Dri

Publié : jeu. 02/juin/2005 12:11
par nico
Quand je déplace la fenêtre, l'animation ne s'arrête pas; par contre si on cache par exemple l'animation sous une autre fenêtre pour la faire ré-apparaitre, l'animation se fige et repart au bout de 3 secondes! et toi?

Publié : jeu. 02/juin/2005 14:53
par Dr. Dri
en fait il faut que j'attende un peu plus longtemps quand je bouge la fenetre (4~5 secondes). Idem quand je passe devant... Dans les deux cas changer de couleur la relance immédiatement.

Dri

Publié : jeu. 02/juin/2005 17:27
par nico
Pour Erix14 :D

Code : Tout sélectionner

;/ Nico le 02/06/05
;/ Création d'un avi avec de l'audio

#streamtypeAUDIO = $73647561
#streamtypeVIDEO = $73646976 
#ICMF_CHOOSE_KEYFRAME=1
#ICMF_CHOOSE_DATARATE=2
#AVIERR_OK=0
#AVIIF_KEYFRAME=$10
#Lib = 0 

Structure bitmap24 
  bmiHeader.BITMAPINFOHEADER 
EndStructure 

Structure msvc
  a.b
  b.b
  c.b
  d.b
EndStructure 

Structure AVISTREAMINFO 
  fccType.l 
  fccHandler.msvc
  dwFlags.l 
  dwCaps.l 
  wPriority.w 
  wLanguage.w 
  dwScale.l 
  dwRate.l 
  dwStart.l 
  dwLength.l 
  dwInitialFrames.l 
  dwSuggestedBufferSize.l
  dwQuality.l 
  dwSampleSize.l 
  rcFrame.RECT  
  dwEditCount.l 
  dwFormatChangeCount.l
  szName.b[64]
EndStructure 

Structure AVICOMPRESSOPTIONS 
  fccType.l
  fccHandler.l
  dwKeyFrameEvery.l
  dwQuality.l
  dwBytesPerSecond.l 
  dwFlags.l
  *lpFormat.l
  cbFormat.l
  *lpParms.l
  cbParms.l 
  dwInterleaveEvery.l
EndStructure 

Structure WAVEFORMATEX
  wFormatTag.w
  nChannels.w
  nSamplesPerSec.l
  nAvgBytesPerSec.l 
  nBlockAlign.w
  wBitsPerSample.w
  cbSize.w 
EndStructure 

NewList bitmap.s()
NewList memoire.l()


;/ Procédure traduite en Pure Basic
;/ d'un code écrit en c++ par son auteur Chiew Heng Wah.

Procedure AddWAV(strFileWAV.s, pfile.l)
  pfileWav.IAVIFILE
  siWav.AVISTREAMINFO
  psWav.IAVISTREAM  
  psAvi.l
  fmtWav.WAVEFORMATEX 
  If CallFunction( #Lib, "AVIFileOpen",@pfileWav, @strFileWAV, #OF_READ, #Null)=0
    If CallFunction( #Lib, "AVIFileGetStream",pfileWav, @psWav, #streamtypeAUDIO, 0)=0
      If CallFunction( #Lib, "AVIStreamInfo",psWav, @siWav, SizeOf(AVISTREAMINFO))=0
        If CallFunction( #Lib, "AVIStreamReadFormat",psWav, 0, #Null, @lFmtSize) =0
          If lFmtSize
            If  CallFunction( #Lib, "AVIStreamReadFormat",psWav, 0, @fmtWav, @lFmtSize)=0
              lStreamLength = CallFunction( #Lib, "AVIStreamLength",psWav)
              If lStreamLength
                lpbData = AllocateMemory(lStreamLength)
                If CallFunction( #Lib, "AVIStreamRead",psWav, 0, lStreamLength, lpbData, lStreamLength, #Null, #Null)=0 
                  If CallFunction( #Lib, "AVIFileCreateStream",pfile, @psAvi, @siWav)=0
                    If CallFunction( #Lib, "AVIStreamSetFormat",psAvi, 0, @fmtWav, lFmtSize)=0
                      If CallFunction( #Lib, "AVIStreamWrite",psAvi, 0, lStreamLength, lpbData, lStreamLength, #AVIIF_KEYFRAME, #Null, #Null)=0
                        val.b=1
                      EndIf
                    EndIf 
                    CallFunction( #Lib, "AVIStreamRelease",psAvi)
                  EndIf
                EndIf
                FreeMemory(lpbData)
              EndIf
            EndIf 
          EndIf 
        EndIf
      EndIf   
      CallFunction( #Lib, "AVIStreamRelease",psWav)
    EndIf 
    CallFunction( #Lib, "AVIFileRelease",pfileWav)
  EndIf 
  ProcedureReturn val
EndProcedure  

Fichier.s = OpenFileRequester("Sélection multiple des Fichiers Bitmaps", "", "Fichiers BMP|*.bmp", 0, #PB_Requester_MultiSelection) 
If Fichier 
  Debug  Fichier 
  AddElement(bitmap())
  bitmap()= Fichier
  Repeat 
    Fichier = NextSelectedFileName() 
    If Fichier 
      AddElement(bitmap())
      bitmap()= Fichier
      Debug Fichier 
    EndIf 
  Until Fichier = "" 
EndIf

ForEach bitmap()
  If ReadFile(0, bitmap()) 
    FileSeek(SizeOf(BITMAPFILEHEADER)) 
    bmi.bitmap24 
    ReadData(@bmi, SizeOf(bitmap24))
    If  bmi\bmiHeader\biWidth
      If  bmi\bmiHeader\biHeight
        If  bmi\bmiHeader\biBitCount
          If  bmi\bmiHeader\bisizeimage=0
            bmi\bmiHeader\bisizeimage=Lof()-54
          EndIf 
            FileSeek(1078)
            AddElement(memoire())
            memoire() =GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT, bmi\bmiHeader\bisizeimage) 
            ReadData(memoire(), bmi\bmiHeader\bisizeimage)
        EndIf
      EndIf
    EndIf 
    CloseFile(0) 
  EndIf 
Next 
  
If OpenLibrary  ( #Lib , "AVIFIL32.DLL") 
  CallFunction ( #Lib,  "AVIFileInit" ) 
  avifile.s = SaveFileRequester ( "Nom du fichier Avi à enregistrer", "", "Video|*.avi", 0 ) 
  If GetExtensionPart(avifile)=""
    avifile=avifile+".avi"
  EndIf 
  Debug avifile
  
  If CallFunction( #Lib, "AVIFileOpen", @pAVIFile.IAVIFILE, @avifile, (#OF_WRITE | #OF_CREATE), 0 )=0
    strhdr.AVISTREAMINFO 
    strhdr\fccType                = #streamtypeVIDEO 
    strhdr\fccHandler\a             = $6D
    strhdr\fccHandler\b             = $73
    strhdr\fccHandler\c             = $76
    strhdr\fccHandler\d             = $63  
    strhdr\dwScale                = 1 ;Nb de frames/secondes 
    strhdr\dwRate                 = 4 ;( 1 à 30)
    strhdr\dwSuggestedBufferSize  = bmi\bmiHeader\biSize
    
    If SetRect_(@strhdr\rcFrame, 0, 0, bmi\bmiHeader\biWidth, bmi\bmiHeader\biHeight) <>0
      If CallFunction( #Lib, "AVIFileCreateStream", pAVIFile, @pAVIStream, @strhdr) =0
        opts.AVICOMPRESSOPTIONS
        Dim aopts(0) 
        aopts(0)=@opts 
        
        If CallFunction( #Lib, "AVISaveOptions", 0, #ICMF_CHOOSE_KEYFRAME | #ICMF_CHOOSE_DATARATE, 1, @pAVIStream, @aopts(0)) =1
          If CallFunction( #Lib, "AVIMakeCompressedStream", @pAVICompressed, pAVIStream, aopts(0), 0)=#AVIERR_OK 
            If CallFunction( #Lib, "AVIStreamSetFormat", pAVICompressed, 0, @bmi, SizeOf(bitmap24)) =0
              ForEach memoire() 
                If memoire() 
                  If CallFunction( #Lib, "AVIStreamWrite", pAVICompressed, index, 1,  memoire() , bmi\bmiHeader\bisizeimage, #AVIIF_KEYFRAME, 0,0) =0
                    index=index+1
                  EndIf  
                EndIf
              Next 
        EndIf 
        CallFunction( #Lib, "AVIStreamRelease", pAVICompressed) 
      EndIf 
      EndIf
      CallFunction( #Lib, "AVIStreamRelease", pAVIStream )
    EndIf
    ;------------------------ Inclure le son -----------------------------------------   
    

    strFileWAV2.s = OpenFileRequester("Sélection d'un Fichier Audio", "", "Fichiers Wav|*.wav", 0) 
    
    If AddWAV(strFileWAV2, pAVIFile)
      a$="Le fichier avi créé contient un fichier audio."
    Else
      a$="Le fichier audio n'a pu être créé."
    EndIf
    
    ;----------------------------------------
      EndIf
    CallFunction( #Lib, "AVIFileRelease", pAVIFile)
  EndIf 
  CallFunction( #Lib, "AVIFileExit" )
  CloseLibrary( #Lib )
  
  ForEach memoire()
    GlobalFree_(memoire())
  Next
  MessageRequester("Info","Nombre de Frames enregistrées: "+Str(index)+Chr(13)+a$)
EndIf

La lecture de l'audio sera plus ou moins complète suivant le nombre de frames de l'avi, je vous laisse à vos essais!

:)

Publié : jeu. 02/juin/2005 19:18
par nico
@Dr Dri,

Je viens d'y regarder d'un peu plus près, je l'ai modifié; tu peux ré-essayer l'animation reprends de suite.

:)

Publié : jeu. 02/juin/2005 19:46
par erix14
Nico, je te remercie infiniment :D :D :D
C'est du très bon travail, je viens de l'essayer et ça marche très bien :D
à charge de revanche :wink:

Publié : jeu. 02/juin/2005 19:55
par Anonyme2
nico a écrit :Pour Erix14 :D
Dommage, j'aurais aimé m'en servir :mrgreen:


Merci Nico pour ce code