Estrarre e salvare singole immagini durante l'esecuzione di un file video mediante il Componente gb.media
Per estrarre e salvare mediante il Componente gb.media singole immagini da un file video durante la sua esecuzione all'interno di un Oggetto DrawingArea, si posono adottare almeno tre modalità. [nota 1]
Indice
Uso delle sole risorse del Componente gb.media
Usando le sole risorse del Componente gb.media, per catturare singole immagini, si farà uso della sotto-proprietà ".Image" della Proprietà ".Video" della Classe MediaPlayer.
Uso della Classe MediaPlayer
Mostriamo un esempio pratico, nel quale con le risorse della Classe MediaPlayer si farà uso di una DrawingArea, nella quale sarà mostrato il video:
Private mp As MediaPlayer Private i As Integer Public Sub Form_Open() Dim da As DrawingArea ' Crea una "DrawingArea" come oggetto GUI da usare per l'uscita video: With da = New DrawingArea(Me) .X = 10 .Y = 10 .W = 300 .H = 300 .Background = Color.Black End With With mp = New MediaPlayer .URL = Media.URL("/percorso/del/file/video") ' Imposta il controllo dell'uscita video da usare: .SetWindow(da) ' [nota 2] End With End Public Sub Button1_Click() ' Esegue il file video: mp.Play() Repeat ' Una brevissima pausa consente di mostrare e di agire sugli eventuali oggetti posti sul Form: Wait 0.01 Label1.Text = "\rDurata del video: " & CStr(Time(0, 0, 0, mp.Duration * 1000)) & " - Tempo trascorso: " & CStr(Time(0, 0, 0, mp.Position * 1000)) Until mp.Position >= mp.Duration End Public Sub Button2_Click() mp.Stop mp.Close End Public Sub ToggleButton1_Click() If ToggleButton1.Value Then mp.Pause Else mp.Play Endif End Public Sub Button3_Click() Dim img As Image Dim s As String img = mp.Video.Image Inc i s = CStr(i) img.Save("/tmp/foto_" & s & ".png", 100) Write "\rImmagine catturata: " & s Flush End
Con applicazione a riga di comando
Vediamo un paio di esempi simili al precedente però con un'applicazione a riga di comando.
Nel primo esempio sarà possibile cattura un'immagine per volta scrivendo nello spazio della console il carattere "c" e successivamente premendo il tasto "Invio" della tastiera. Se si premerà solo e semplicemente il tasto "Invio", il programma verrà terminato.
Private bo As Boolean Private mp As New MediaPlayer Private i As Integer Public Sub Main() mp.URL = Media.URL("/percorso/del/file/video") mp.Play Print "Durata del video: " & CStr(Time(0, 0, 0, mp.Duration * 1000)) Repeat Wait 0.01 Until (mp.Position >= mp.Duration) Or (bo = True) mp.Close Quit End Public Sub Application_Read() Dim img As Image Dim s As String Input s If s = "c" Then img = mp.Video.Image Inc i s = CStr(i) img.Save("/tmp/imm/foto_" & s & ".png", 100) Print "Immagine catturata: " & s Print Else bo = True Endif End
In quest'altro esempio la cattura sarà continua sino al termine del video:
Private mp As New MediaPlayer Private i As Integer Public Sub Main() mp.URL = Media.URL("/percorso/del/file/video") mp.Play Print "Durata del video: " & CStr(Time(0, 0, 0, mp.Duration * 1000)) Repeat Wait 0.001 Until (mp.Position >= mp.Duration) mp.Close Quit End Public Sub Application_Read() Dim img As Image img = mp.Video.Image Inc i s = CStr(i) img.Save("/tmp/imm/foto_" & s & ".png", 100) Print "Immagine catturata: " & s End
Uso delle Classi MediaPipeline e MediaControl
Mostriamo un esempio pratico in ambiente grafico con le Classi MediaPipeline e MediaControl:
Private pl As MediaPipeline Private bo As Boolean Public Sub Button1_Click() Dim src, vbin, vcon, vsnk, asrc, abin, acon, ares, asnk As MediaControl Dim filevideo As String filevideo = "/percorso/del/file/video" pl = New MediaPipeline As "PLine" src = New MediaControl(pl, "filesrc") src["location"] = filevideo ' Imposta i necessari MediaControl: vbin = New MediaControl(pl, "decodebin") vcon = New MediaControl(pl, "videoconvert") vsnk = New MediaControl(pl, "xvimagesink") abin = New MediaControl(pl, "decodebin") acon = New MediaControl(pl, "audioconvert") ares = New MediaControl(pl, "audioresample") asnk = New MediaControl(pl, "autoaudiosink") ' Connette i "MediaControl" precedentemente impostati: src.LinkTo(vbin) vbin.LinkLaterTo(vcon) vcon.LinkTo(vsnk) asrc = New MediaControl(pl, "filesrc") asrc["location"] = filevideo asrc.LinkTo(abin) abin.LinkLaterTo(acon) acon.LinkTo(ares) ares.LinkTo(asnk) ' Imposta la superficie grafica ove mostrare il video: vsnk.SetWindow(DrawingArea1) pl.Play() While Not bo Wait 0.01 Wend pl.Close End Public Sub PLine_Position() ' Mostra il tempo trascorso dall'avvio del video: Me.Title = "Tempo: " & Format(Time(0, 0, 0, pl.Position * 1000), "hh:nn:ss") End Public Sub PLine_End() ' Questo Evento viene sollevato, quando la conversione è terminata bo = True End Public Sub Button2_Click() ' Cliccando sul "Button" si cattura una immagine di quanto mostrato dalla "DrawingArea" Dim pl2 As New MediaPipeline Dim xis, con, enc, snk As MediaControl xis = New MediaControl(pl2, "ximagesrc") xis["xid"] = DrawingArea1.Id con = New MediaControl(pl2, "videoconvert") enc = New MediaControl(pl2, "pngenc") snk = New MediaControl(pl2, "filesink") snk["location"] = "/tmp" &/ Format(Now, "dd_mm_yyyy-hh_nn_ss") & ".png" ' Collega fra loro i plugin di "GStreamer": xis.LinkTo(con) con.LinkTo(enc) enc.LinkTo(snk) ' Effettua la cattura di quanto mostrato dalla "DrawingArea": pl2.Play() pl2.Stop pl2.Close End
Usando il plugin "multifilesrc" di GStreamer
Mostriamo un esempio, questa volta a riga di comando, nel quale si cattureranno più fotogrammi del file video mediante il plugin "multifilesink" di GStreamer:
Public Sub Main() Dim pl As MediaPipeline Dim src, dcb, vcn, enc, snk As MediaControl Dim i, post As Integer If Not Exist("/tmp/IMMAGINI") Then Mkdir "/tmp/IMMAGINI" pl = New MediaPipeline src = New MediaControl(pl, "filesrc") src["location"] = "/percorso/del/file/video" dcb = New MediaControl(pl, "decodebin") vcn = New MediaControl(pl, "videoconvert") enc = New MediaControl(pl, "pngenc") snk = New MediaControl(pl, "multifilesink") ' Per i nomi dei singoli file PNG si imposta un numero progressivo formato da 5 cifre decimali: snk["location"] = "/tmp/IMMAGINI/frame%05d.png" ' Collega fra loro i plugin di "GStreamer": src.LinkTo(dcb) dcb.LinkLaterTo(vcn) vcn.LinkTo(enc) enc.LinkTo(snk) ' Effettua la ripresa delle immagini: pl.Play() Write "Attendere...." Flush Repeat post = i Wait 0.1 i = Dir("/tmp/IMMAGINI", "*", gb.File).Count Until post == i pl.Stop() pl.Close() Print "\nCattura immagini effettuata" End
Uso delle risorse della Classe MediaPlayer e della Classe DesktopWindow
Unitamente alle risorse della Classe MediaPlayer, si potrà fare uso anche del Metodo ".GetScreenshot()" della Classe DesktopWindow. BR>Bisognerà attivare anche i Componenti gb.desktop e gb.desktop.x11.
Mostriamo un esempio pratico, nel quale cliccando su Button1 viene avviato il video. Quando si desidera catturare un'immagine dal video, si deve premere "Button2". Per terminare il programma e creare i file immagine, premere "Button3". I file immagine saranno salvati nel percorso "/tmp/immago".
Private mp As MediaPlayer Private da As DrawingArea Private pc As New Picture[] Public Sub Form_Open() ' Crea una "DrawingArea" come oggetto GUI da usare per l'uscita video: With da = New DrawingArea(Me) .X = 10 .Y = 10 .W = 480 .H = 320 .Background = Color.Black End With With mp = New MediaPlayer .URL = Media.URL("/percorso/del/file/video") ' Imposta il controllo dell'uscita video da usare: .SetWindow(da) End With End Public Sub Button1_Click() ' Avvia l'esecuzione del video: mp.Play() End Public Sub Button2_Click() Dim dw As DesktopWindow dw = New DesktopWindow(da.Handle) ' Cattura una schermata del contenuto video mostrato in quel momento dalla "DrawingArea": pc.Push(dw.GetScreenshot(True)) End Public Sub Button3_Click() Dim i As Integer Dim drc, s As String ' Arresta l'esecuzione del file video nella "DrawingArea": mp.Stop() drc = "/tmp/immago" If Not Exist(drc) Then Mkdir drc Else For Each s In Dir(drc, "picture_*", gb.file) Kill drc &/ s Next Endif ' Genera infine i vari file immagine di formato .png: For i = 0 To pc.Max pc[i].Save(drc &/ "picture_" & CStr(i) & ".png", 100) Next End
Uso delle risorse della Classe MediaPlayer e della Classe Desktop
Unitamente alle risorse della Classe MediaPlayer, si potrà anche fare uso del Metodo ".Screenshot()" della Classe Desktop. Anche in questo caso bisognerà attivare i Componenti gb.desktop e gb.desktop.x11.
Facendo riferimento all'esempio di codice precedente, la sub-routine dell'evento "Button2_Click( )" dovrà essere modificata come segue:
Public Sub Button2_Click() ' Cattura una schermata del contenuto video mostrato in quel momento dalla "DrawingArea": pc.Push(Desktop.Screenshot(da.ScreenX, da.ScreenY, da.W, da.H)) End
Note
[1] Vedere anche le seguenti pagine della wiki:
- Estrarre e salvare singole immagini da una ripresa video mediante WebCam effettuata con il Componente gb.media
- Catturare singole immagini da quanto mostrato dal Controllo MediaView del Componente gb.media.form
[2] Riguardo all'Oggetto grafico da usare con il Metodo ".SetWindow()" della Classe "MediaPlayer", B. Minisini ha chiarito che esso necessita di un controllo che avesse una vera finestra X11 (o ayland), altrimenti se userà il primo controllo genitore con una finestra reale, che di solito è quella di primo livello.