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 unechaîne=ComplèteRep(fRepExe())+"vignette.jpg"

SIdSauveImageJPEG(IMG_CréationVignette,sNomFichier,85) =FauxALORS
Erreur("Impossible d'enregistrer le fichier : "+sNomFichier,ErreurInfo())
SINON SIHAttacheMémo(Video,Vignette,sNomFichier,hMemoImg) =FauxALORS
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 :
ProcedureTakeSnapshot(num est unentier,chemin est unechaîne,...
largeur est unentier,hauteur est unentier)

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


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 unestructure
biSize est unentier//Type C : DWORD
biWidth est unentier//Type C : LONG
biHeight est unentier//Type C : LONG
biPlanes est unentiersur2octets//Type C : WORD
biBitCount est unentiersur2octets//Type C : WORD
biCompression est unentier//Type C : DWORD
biSizeImage est unentier//Type C : DWORD
biXPelsPerMeter est unentier//Type C : LONG
biYPelsPerMeter est unentier//Type C : LONG
biClrUsed est unentier//Type C : DWORD
biClrImportant est unentier//Type C : DWORD
FIN



AVIFILEINFO est unestructure
dwMaxBytesPerSec est unentier
dwFlags est unentier
dwCaps est unentier
dwStreams est unentier
dwSuggestedBufferSize est unentier
dwWidth est unentier
dwHeight est unentier
dwScale est unentier
dwRate est unentier
dwLength est unentier
dwEditCount est unentier
szFileType est unechaîneASCIIZsur64// ????
FIN








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

srccopy est unentier
srccopy=0x00CC0020


ffile est un AVIFILEINFO
pavif est unentier= &ffile

pavis est unentier
streamtypeVIDEO est unentier=1935960438


lIndex est unentier=aindex


fn est unechaîne
fn=afavi


hr est unentier

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 unentier

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

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

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

//=====================
hddOp,hdcDisplay est unentier
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 unechaî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 unechaî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".