PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2024 → [WD17] Capturer image d'une vidéo
[WD17] Capturer image d'une vidéo
Débuté par BERNARD Julien, 30 mar. 2012 14:58 - 21 réponses
Posté le 30 mars 2012 - 14:58
Bonjour,

Je cherche à créer une vignette d'une vidéo afin de l'afficher dans une table servant à lister les vidéos disponibles.

Je ne parvient pas à capturer une image de cette vidéo.

J'ai essayé en vain les solutions suivantes :
- jouer la vidéo dans un champ Multimédia et copier le contenu dans une image pour ensuite l'enregistrer
- jouer la vidéo dans une autre fenêtre avec les fonction MCI pour ensuite faire une copie d'écran de cette fenêtre où se joue la vidéo mais on ne voit pas la vidéo, juste du noir ...

Je vous remercie par avance pour votre aide
Posté le 03 avril 2012 - 11:58
un début de réponse :

j'utilise les fonctions MCI pour afficher une vidéo dans un champ image :

MCIOuvre(sUneVidéo,"VignetteVideo",MciStyleFille,IMG_CréationVignette,MciModeHomothétiqueCentré)
MCIJoue("VignetteVideo")
MCIPause("VignetteVideo")

Ensuite j'enregistre l'image dans un fichier et je la stocke dans la bdd :

dSauveImageJPEG(IMG_CréationVignette,"vignette.jpg",85)
HAttacheMémo(Video,Vignette,ComplèteRep(fRepExe())+"vignette.jpg",hMémoImg)
HAjoute(Video)

Résultat la vignette est vide (blanche en fait) ...

la fonction dSauveImageJPEG ne parvient pas à capturer le flux vidéo ...

merci par avance pour votre aide
Membre enregistré
511 messages
Popularité : +18 (18 votes)
Posté le 04 avril 2012 - 12:13
Bonjour Julien,

Es-tu certain que le fichier JPEG est créé ?

Avec un code plus robuste et rigoureux tu pourrais t'en assurer. ;-)

sNomFichier est une chaîne = ComplèteRep(fRepExe())+"vignette.jpg"

SI dSauveImageJPEG(IMG_CréationVignette,sNomFichier,85) = Faux ALORS
Erreur("Impossible d'enregistrer le fichier : " + sNomFichier, ErreurInfo())
SINON SI HAttacheMémo(Video,Vignette,sNomFichier,hMemoImg) = Faux ALORS
Erreur("Erreur HyperFileSQL : " + HErreur())
SINON
HAjoute(Video)
FIN


BERNARD Julien a écrit dans le message de news <5e6c9ebc05452ab47ae8a3a91246270d@news.pcsoft> :
un début de réponse :

j'utilise les fonctions MCI pour afficher une vidéo dans un champ image :

MCIOuvre(sUneVidéo,"VignetteVideo",MciStyleFille,IMG_CréationVignette,MciModeHomothétiqueCentré)
MCIJoue("VignetteVideo")
MCIPause("VignetteVideo")

Ensuite j'enregistre l'image dans un fichier et je la stocke dans la bdd :

dSauveImageJPEG(IMG_CréationVignette,"vignette.jpg",85)
HAttacheMémo(Video,Vignette,ComplèteRep(fRepExe())+"vignette.jpg",hMémoImg)
HAjoute(Video)

Résultat la vignette est vide (blanche en fait) ...

la fonction dSauveImageJPEG ne parvient pas à capturer le flux vidéo ...

merci par avance pour votre aide


--
Pour me contacter par courrier électronique, cliquez sur le lien ci-dessous (protection antispam): http://cerbermail.com/…
Posté le 04 avril 2012 - 13:52
Bonjour,

oui oui le fichier jpeg est créé mais il est tout noir ...

en effet mon code n'est pas rigoureux mais servait pour un test rapide ...

Le soucis c'est que de cette façon le flux vidéo n'est pas enregistré, de la même manière que si on fait une copie d'écran depuis le clavier.
Posté le 04 avril 2012 - 15:20
Bonjour,

Je travaille sur un projet similaire, et j'utilise la copie d'écran.

Par contre, je rencontre quelques bugs sous xp (pas sur mon seven).
Les solutions que j'ai trouvées :
- mettre à jour le driver écran
- désactiver les accélérations DirectDraw et Direct3D de la carte graphique

Normalement, après ces modifications, il est possible de faire une copie
d'écran avec la vidéo.
Merci de faire part de vos retours.

Frank

"BERNARD Julien" a écrit dans le message de groupe de discussion :
32abe91107a989e8b4bf680c80b8f1aa@news.pcsoft...


Bonjour,

oui oui le fichier jpeg est créé mais il est tout noir ...

en effet mon code n'est pas rigoureux mais servait pour un test rapide ...

Le soucis c'est que de cette façon le flux vidéo n'est pas enregistré, de la
même manière que si on fait une copie d'écran depuis le clavier.
Posté le 04 avril 2012 - 16:38
Merci Frank

mais mon soucis c'est que mon appli sera déployée sur des dizaines de postes et je ne peux demander à chacun de faire ces manip ...

Je vais tester sur mon poste mais je ne pense pas que je vais pouvoir utiliser cette solution ...
Membre enregistré
101 messages
Popularité : +7 (7 votes)
Posté le 04 avril 2012 - 20:32
Salut,

As tu essayé de faire un dDebutDessin avant le dSauveImageJPEG ?
(ensuite après il faudra faire un dFinDessin)

@+
Maax°(51)°
Membre enregistré
511 messages
Popularité : +18 (18 votes)
Posté le 04 avril 2012 - 23:34
Bonjour à Julien, et aux autres contributeurs, :-)

BERNARD Julien a écrit dans le message de news <32abe91107a989e8b4bf680c80b8f1aa@news.pcsoft> :

oui oui le fichier jpeg est créé mais il est tout noir ...


J'ai une explication pour ce phénomène.
En fait la fonction MCIOuvre avec l'option MciStyleFille n'utilise pas directement le champ image IMG_CréationVignette.

Déjà dans cette discussion, il faut comprendre que, pour Windows:
• un champ WinDev est un "objet fenêtré" : c'est une fenêtre.
• toute fenêtre Windows peut avoir une ou plusieurs fenêtres enfants.

Et c'est ce qui se passe avec la fonction MCIOuvre + l'option MciStyleFille :
cette fonction crée une fenêtre enfant (de classe AVIWnd32) rattachée à IMG_CréationVignette (qui est donc son parent).

C'est cette fenêtre enfant qui est utilisée pour afficher la vidéo.
Quant au champ IMG_CréationVignette, il ne contient aucune image.

Alors, est-il possible de "capturer" l'image présentée dans la "fenêtre enfant MCI" ?

--
Pour me contacter par courrier électronique, cliquez sur le lien ci-dessous (protection antispam): http://cerbermail.com/…
Membre enregistré
101 messages
Popularité : +7 (7 votes)
Posté le 05 avril 2012 - 12:06
Salut,

-JOB- : d'où ma proposition d'utiliser dDébutDessin sur le champ image avant d'en faire la sauvegarde. Si je ne me trompe pas dDébutDessin fait une "copie" de tout ce qu'il y a dessous, dedans et sur le champ image à ses coordonnées avant de démarrer le dessin (on peut s'en convaincre en mettant un champ en dessous si l'image est transparente).
Donc comme la vidéo est dessinée sur le champ image, dDebutDessin, en théorie (je n'ai pas essayé) devrait "capturer" l'image actuellement affichée; et donc dSauveImageJPEG sauvegardera à son tour l'image déjà capturée par dDébutDessin.

Ma modeste contribution au sujet...
@+
Maax°(51)°
Membre enregistré
283 messages
Popularité : +3 (3 votes)
Posté le 05 avril 2012 - 12:26
Bonjour tout le monde,

J'ai réalisé des progs sur la vidéo il y a plus de 15 ans et sous visual basic.

Donc, soyez indulgents si tout n'est pas exact car les infos suivantes sont "de mémoire" et ne tiennent pas compte si de nouvelles technologies ont été ajoutées au noyau Windows.

1 ) la vidéo est projetée en "overlay", autrement dit directement sur l'écran en contournant la gestion des fenêtres de Windows. La fenêtre ne sert qu'à définir le rectangle de projection.
2 ) C'est certainement ce qui empêche de faire une copie d'écran puisque la fenêtre ne contient rien.
3 ) Les fonctions MCI ne m'avaient pas beaucoup aidé.
4 ) J'utilisais les fonctions de DLL pour manipuler les vidéos (fournies par le fabricant de la caméra ? je ne me souviens plus)

Pour ton cas précis, j'oublierais les fonctions WD et m'orienterais vers des activeX ou DLL. Je ne suis pas sûr mais je crois que VLC de Videolan en a une.

J'espère avoir aidé un peu (surtout à ne pas perdre de temps)

Bon dev et A+
Posté le 05 avril 2012 - 19:37
Je vous remercie tous pour vos réponses.
Je me rend compte que c'est un sujet qui intéresse ...

Je viens de tester en ajoutant dDébutDessin() ...

mais cela ne fonctionne pas, l'image reste blanche ...

L'utilisation de dll externe me gêne un peu, j'aimerai trouver une solution autre, "purement" windev ...

Je continue de tester et de chercher, si quelqu'un à des idées qu'il n'hésite pas.

merci pour tout
Membre enregistré
352 messages
Popularité : +13 (17 votes)
Posté le 05 avril 2012 - 19:48
Bonjour,

Je n'ai pas essayé mais avec un dCopieImageEcran() puis affection du résultat dans un autre champ image, puis un dSauveImage de ce champ ?

C'est juste une idée !!
BON DEV
Membre enregistré
962 messages
Popularité : +183 (185 votes)
Posté le 05 avril 2012 - 20:04
bonjour,
en utilisant l'exemple de la classe clibvlc (interface avec videolan) disponible ici :
http://depot.pcsoft.fr/resource.awp…
ce n'est pas très compliqué pour faire un snapshot d'une image d'une vidéo que l'on est en train de lire.
Il faut rajouter une procédure dans la classe cLibVLC :
Procedure TakeSnapshot(num est un entier,chemin est une chaîne,...
largeur est un entier,hauteur est un entier)

res est un entier
SI :mp <> 0
res = API(:sDLL,"libvlc_video_take_snapshot",:mp,num,chemin,largeur,hauteur)
SI res = 0 ALORS
:AddToLog("SnapShot")
SINON
:AddToLog("SnapShot : Vidéo non trouvée")
FIN
FIN
RENVOYER 0


et un bouton (avec comme nom Photo par exemple) dans la fenêtre principale de l'exemple avec comme code :
oVLC:TakeSnapshot(0,"F:\temp\out.png",352,288)


et hop vous lancez la lecture d'une vidéo par le bouton Lire et lorsque vous appuyez sur le bouton Photo une copie de l'image en cours est écrite dans out.png. La contrainte c'est qu'il faut que VLC soit installé sur votre PC et je ne sais pas si la classe marche encore avec la nouvelle version de VLC.

Ami calmant, J.P ;-)
Membre enregistré
283 messages
Popularité : +3 (3 votes)
Posté le 05 avril 2012 - 20:06
Re-bonjour,

Ça vient de me revenir à l'instant : mon histoire de "overlay" c'était pour un affichage direct caméra --> écran et non affichage d'un film vidéo déjà enregistré sur disque.

Bon dev et A+
Posté le 06 avril 2012 - 01:17
C'est la solution que j'ai trouvée, mais je rencontre le même problème,
l'application doit être déployée sur plusieurs postes ...
Par contre, sur mon Seven, tout fonctionne parfaitement, pas besoin de
toucher à l'accélération matérielle.

Frank

"BERNARD Julien" a écrit dans le message de groupe de discussion :
7176e0b8881676b4b017132740d8c441@news.pcsoft...


Merci Frank

mais mon soucis c'est que mon appli sera déployée sur des dizaines de postes
et je ne peux demander à chacun de faire ces manip ...

Je vais tester sur mon poste mais je ne pense pas que je vais pouvoir
utiliser cette solution ...
Membre enregistré
962 messages
Popularité : +183 (185 votes)
Posté le 10 avril 2012 - 07:38
Bonjour,
comme le suggère Pat 16, on peut essayer de faire une copie totale de l'écran et ne prendre que la partie de l'affichage de la vidéo pour la mettre dans un champ image invisible. Cela marche chez moi avec ce code en WD16 sous Win7 (je n'ai pas essayé sous XP) :
1 - Lecture du fichier vidéo
MCIOuvre("f:\Mavideo.wmv","VignetteVideo", MciStyleFille,IMG_CréationVignette,MciModeHomothétiqueCentré)
MCIJoue("VignetteVideo")

et voici pour le code du bouton qui fait la capture ( le champ image invisible est IMG_CAPTURE). On sauvegarde dans l'exemple en png. :
// J.P Avril 2012
// copie Ecran mais on ne prend qu'une partie
dCopieImage(copieEcran,IMG_CAPTURE,copieSrcCopie,...
IMG_CréationVignette..X + FenIntPosX ,IMG_CréationVignette..Y + FenIntPosY,...
IMG_CréationVignette..Hauteur,IMG_CréationVignette..Largeur)
dSauveImagePNG(IMG_CAPTURE,"f:\vignette.png")

En ce qui concerne VLC la libvlc est passée en licence LGPL ce qui signifie que normalement on a le droit de l'utiliser dans des applications non GPL. La classe clibvlc a l'air de fonctionner en version VLC 2.0 .

Ami calmant, J.P ;-)
Membre enregistré
511 messages
Popularité : +18 (18 votes)
Posté le 10 avril 2012 - 12:57
Bonjour à tous,

Merci J.P. pour ta contribution.
Je viens de tester ton code sous Windows XP et c'est parfait. :-)

Jurassic Pork a écrit dans le message de news <fb74511c6f5e75224a421f8a60cc6330@news.pcsoft> :
Bonjour,
comme le suggère Pat 16, on peut essayer de faire une copie totale de l'écran et ne prendre que la partie de l'affichage de la vidéo pour la mettre dans un champ image invisible. Cela marche chez moi avec ce code en WD16 sous Win7 (je n'ai pas essayé sous XP) :



--
Pour me contacter par courrier électronique, cliquez sur le lien ci-dessous (protection antispam): http://cerbermail.com/…
Posté le 12 avril 2012 - 17:11
Bonjour à tous,

Je reviens vers vous car je viens de tester la solution de J.P. ...

J'ai toujours le même soucis, il ne capture pas la vidéo.

Sous Vista, il capture même ce qu'il y a en dessous de la vidéo, par exemple il va capturer les icônes présent sur le bureau mais pas la vidéo !

Je sèche là ...

je suis sous WD17 ...
Membre enregistré
352 messages
Popularité : +13 (17 votes)
Posté le 12 avril 2012 - 19:15
Bonjour,
Je viens d'essayer le code de JP, je suis en WD16 WIn7 64 Pro
cela fonctionne si on fait la copie pendant la vidéo, mais si on fait pause l'image de la vidéo disparait ne s'affiche plus ! donc normale que la copie soit vide
il semblerais que ce soit le "pause" qui "pose" problème
Posté le 12 avril 2012 - 21:38
Dans mon test je ne fais pas de pause ...
Posté le 23 avril 2012 - 16:18
si cela peut aider

voila une fonction qui permet de créer une vignette sans avoir à "jouer" la video

elle a besoin en paramètre du chemin et du nom de la vidèo et ensuite du n° du frame de la vidéo. Le résultat de l'image se trouve ensuite dans un champ image IMG_VIGNETTE



BITMAPINFOHEADER est une structure
biSize est un entier //Type C : DWORD
biWidth est un entier //Type C : LONG
biHeight est un entier //Type C : LONG
biPlanes est un entier sur 2 octets //Type C : WORD
biBitCount est un entier sur 2 octets //Type C : WORD
biCompression est un entier //Type C : DWORD
biSizeImage est un entier //Type C : DWORD
biXPelsPerMeter est un entier //Type C : LONG
biYPelsPerMeter est un entier //Type C : LONG
biClrUsed est un entier //Type C : DWORD
biClrImportant est un entier //Type C : DWORD
FIN



AVIFILEINFO est une structure
dwMaxBytesPerSec est un entier
dwFlags est un entier
dwCaps est un entier
dwStreams est un entier
dwSuggestedBufferSize est un entier
dwWidth est un entier
dwHeight est un entier
dwScale est un entier
dwRate est un entier
dwLength est un entier
dwEditCount est un entier
szFileType est une chaîne ASCIIZ sur 64 // ????
FIN








Procedure GET_FRAME(afavi,aindex=0)
{FenEnCours()+".IMG_VIGNETTE",indChamp}..Visible=Faux

srccopy est un entier
srccopy=0x00CC0020


ffile est un AVIFILEINFO
pavif est un entier = &ffile

pavis est un entier
streamtypeVIDEO est un entier =1935960438


lIndex est un entier =aindex


fn est une chaîne
fn=afavi


hr est un entier

AppelDLL32("avifil32","AVIFileInit")
hr = AppelDLL32("avifil32","AVIFileOpenA",&pavif, &fn, 0, Null)


SI (hr <> 0)
AppelDLL32("avifil32","AVIFileExit")
Info("AVi erreur",NumériqueVersChaîne(hr,"x"))
RENVOYER(0)
FIN


hr=AppelDLL32("avifil32","AVIFileGetStream",pavif, &pavis,streamtypeVIDEO, 0);

pFrame est un entier

pFrame= AppelDLL32("avifil32","AVIStreamGetFrameOpen",pavis, 1)

pdib est un entier
pdib = AppelDLL32("avifil32","AVIStreamGetFrame",pFrame, lIndex)

//=============================
tt est BITMAPINFOHEADER
Transfert(&tt,pdib,Dimension(tt))

//=====================
hddOp,hdcDisplay est un entier
hddOp=AppelDLL32("msvfw32","DrawDibOpen")

// Initialisation des propriétés de l'objet DrawDib

{FenEnCours()+".IMG_VIGNETTE",indChamp}..Largeur=tt.biWidth
{FenEnCours()+".IMG_VIGNETTE",indChamp}..Hauteur=tt.biHeight

hdcDisplay=dDébutDessin(FenEnCours()+".IMG_VIGNETTE")


hr=AppelDLL32("msvfw32","DrawDibBegin",hddOp, hdcDisplay, 0, 0, pdib, tt.biWidth,tt.biHeight, 4)

szBuffering est une chaîne

szBuffering=Répète(Null,tt.biSizeImage )

Transfert(&szBuffering,pdib+Dimension(tt),tt.biSizeImage)


hr=AppelDLL32("msvfw32","DrawDibDraw",hddOp, hdcDisplay, 0, 0, tt.biWidth,tt.biHeight, pdib, szBuffering, 0, 0, tt.biWidth, tt.biHeight, 0);



hr=AppelDLL32("msvfw32","DrawDibClose",hddOp)

//========================================================================

// Libération des ressources du flux video
AppelDLL32("avifil32","AVIStreamRelease",pavis)

AppelDLL32("avifil32","AVIFileRelease",pavif)

AppelDLL32("avifil32","AVIFileExit")



ttmem est une chaîne

ttmem=dSauveImageBMP(FenEnCours()+".IMG_VIGNETTE",enMémoire)

{FenEnCours()+".IMG_VIGNETTE",indChamp}..Largeur={FenEnCours()+".IMG_VIGNETTE",indChamp}..LargeurInitiale
{FenEnCours()+".IMG_VIGNETTE",indChamp}..Hauteur={FenEnCours()+".IMG_VIGNETTE",indChamp}..HauteurInitiale


{FenEnCours()+".IMG_VIGNETTE",indChamp}=ttmem



{FenEnCours()+".IMG_VIGNETTE",indChamp}..Visible=Vrai


RENVOYER(Vrai)



Stéphane
Membre enregistré
6 messages
Posté le 11 juin 2019 - 16:33
Bonjour,

Est-ce que quelqu'un a réussi à faire fonctionner le code de Stéphane après toutes ces années ?
J'ai simplement une erreur lors de l'utilisation de la méthode "Transfert".