Public Sub RunEncoder()
Dim Encoded As String[] 'la lista delle path di tutti i file dalla sorgente da codificare
Dim I As Integer
Dim OutputFileName As String
Encoded = FileChooser_Sorgente.SelectedPaths
Do While Not ((bChiudo = True) Or (Encoded.count = 0)) 'fino a che non ho codificato tutti i file, oppure fino a quando non si preme "cancel"
'codifica 'ffmpeg -i "$f" -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 "$( sed -e's/\.mpg/.mkv/g' <<< $f )"
'Debug Encoded[0]
OutputFileName = File.BaseName(Encoded[0])
OutputFileName = Replace(OutputFileName, " ", "_")
'$hProcess = Exec ["ffmpeg", "-i", Encoded[0], "-c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 ", FileChooser_Destinazione.Dir & "/" & File.Name(Encoded[0]) & ".mkv"] Wait
'$hProcess = Exec ["ffmpeg", "-i", Encoded[0], "-c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2", FileChooser_Destinazione.Dir & "/" & "test.mkv"] Wait
Debug "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 " & FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv"
'Shell "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 " & FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv" wait
$hProcess = Shell "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 " & FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv"
'se la codifica e' andata bene allora lo rimuovo
Encoded.Remove(0)
Loop
End
c'e' ne fosse una delle righe di codifica che mi funziona ......
grande mistero .....
a parte le mille righe tentete piu' o meno in confusione, lo spezzone di codice riempie un vettore di stringhe con la lista di file da ricodificare in h265.
l'idea e' processare il primo, verificare che il processo sia terminato sensa errori, eliminare il primo elemento dal vettore e continuare a codificare.
Fino a che il vettore non e' vuoto o si e' premuto il tasto annulla 8nel qual caso si ritorna all'interfaccia originale).
In pratica e' un encoder batch di file video.
Il problema e' che (a parte passare tutto il comando ad una shell, in modo un po' brutale), non riesco ad ottenere nulla da ffmpeg (che passato direttamente da terminale va benissimo).
OutputFileName = File.BaseName(Encoded[0])
OutputFileName = Replace(OutputFileName, " ", "_")
OutputFileName = FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv"
comando = "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 " & OutputFileName
$hProcess = Shell comando
manda il processo in esecuzione e questo non si ferma piu' e non genera nel filesystem ALCUN file mkv.
Avere un'idea dello stato di codifica di ffmpeg sarebbe chiedere troppo, ma almeno vedere un file che cresce di dimensione .....
manda il processo in esecuzione e questo non si ferma piu'....
Inizierei a controllare il ciclo: ma...... non è che sarebbe meglio un ciclo Do....Loop Until ?
Do
.......
.......
Loop Unitl Not ((bChiudo = True) Or (Encoded.count = 0)) ' Gira fino a che la variabile "bChiudo" non diventa "Not True" (ossia "False") oppure fino a che "Encoded.Count" non diventa = 0
Prova un po'.
si, di suo ffmpeg in un terminale funziona benissimo, se io prendo quello che scrive debug e lo butto in un terminale, da qualunque parte del filesystem io sia, ffmpeg inizia a leggere il file mpg e butta re fuori il file mkv codificato x265 ....
Public Sub RunEncoder()
Dim Encoded As String[] 'la lista delle path di tutti i file dalla sorgente da codificare
Dim I As Integer
Dim OutputFileName As String
Dim comando As String
Encoded = FileChooser_Sorgente.SelectedPaths
Do While Not ((bChiudo = True) Or (Encoded.count = 0)) 'fino a che non ho codificato tutti i file, oppure fino a quando non si preme "cancel"
'codifica 'ffmpeg -i "$f" -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 "$( sed -e's/\.mpg/.mkv/g' <<< $f )"
OutputFileName = File.BaseName(Encoded[0])
OutputFileName = Replace(OutputFileName, " ", "_")
OutputFileName = FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv"
comando = "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 " & OutputFileName
Debug comando
Shell comando
'$hProcess = Exec ["ffmpeg", "-i", Encoded[0], "-c:v", "libx265", "-preset", "medium", "-crf", "28", "-c:a", "aac", "-b:a", "128k", "-strict -2" & user.Home & "/Scrivania/test" & ".mkv"]
'$hProcess = Exec ["ffmpeg", "-i", Encoded[0], "-c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 ", OutputFileName] Wait
'$hProcess = Exec ["ffmpeg", "-i", Encoded[0], "-c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2", FileChooser_Destinazione.Dir & "/" & "test.mkv"] Wait
'Shell "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 " & FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv" wait
'$hProcess = Shell "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 " & FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv"
'se la codifica e' andata bene allora lo rimuovo
Encoded.Remove(0)
Loop
ToggleButton_encode.Value = 0
End
per esempio comando mi da':
FMain.RunEncoder.119: ffmpeg -i /home/v1p3r/TG/2014/tg_01102014.mpg -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 /home/v1p3r/TG/tg_01102014.mkv
e se io prendo il comando di ffmpeg e lo butto in un terminale, l'encoder parte senza problemi:
ffmpeg -i /home/v1p3r/TG/2014/tg_01102014.mpg -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 /home/v1p3r/TG/tg_01102014.mkvffmpeg version 2.8.6-1ubuntu2 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 5.3.1 (Ubuntu 5.3.1-11ubuntu1) 20160311
configuration: --prefix=/usr --extra-version=1ubuntu2 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv
libavutil 54. 31.100 / 54. 31.100
libavcodec 56. 60.100 / 56. 60.100
libavformat 56. 40.101 / 56. 40.101
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 40.101 / 5. 40.101
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.101 / 1. 2.101
libpostproc 53. 3.100 / 53. 3.100
Input #0, mpeg, from '/home/v1p3r/TG/2014/tg_01102014.mpg':
Duration: 00:20:57.00, start: 0.270000, bitrate: 6281 kb/s
Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], max. 9500 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
Stream #0:1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16p, 224 kb/s
x265 [info]: HEVC encoder version 1.9
x265 [info]: build info [Linux][GCC 5.3.1][64 bit] 8bit+10bit+12bit
x265 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
x265 [info]: Main profile, Level-3 (Main tier)
x265 [info]: Thread pool created using 8 threads
x265 [info]: frame threads / pool features : 3 / wpp(9 rows)
x265 [warning]: Source height < 720p; disabling lookahead-slices
x265 [info]: Coding QT: max CU size, min CU size : 64 / 8
x265 [info]: Residual QT: max TU size, max depth : 32 / 1 inter / 1 intra
x265 [info]: ME / range / subpel / merge : hex / 57 / 2 / 2
x265 [info]: Keyframe min / max / scenecut : 25 / 250 / 40
x265 [info]: Lookahead / bframes / badapt : 20 / 4 / 2
x265 [info]: b-pyramid / weightp / weightb : 1 / 1 / 0
x265 [info]: References / ref-limit cu / depth : 3 / 1 / 1
x265 [info]: AQ: mode / str / qg-size / cu-tree : 1 / 1.0 / 32 / 1
x265 [info]: Rate Control / qCompress : CRF-28.0 / 0.60
x265 [info]: tools: rd=3 psy-rd=2.00 signhide tmvp strong-intra-smoothing
x265 [info]: tools: deblock sao
Output #0, matroska, to '/home/v1p3r/TG/tg_01102014.mkv':
Metadata:
encoder : Lavf56.40.101
Stream #0:0: Video: hevc (libx265), yuv420p, 720x576 [SAR 16:15 DAR 4:3], q=2-31, 25 fps, 1k tbn, 25 tbc
Metadata:
encoder : Lavc56.60.100 libx265
Stream #0:1: Audio: aac ([255][0][0][0] / 0x00FF), 48000 Hz, stereo, fltp, 128 kb/s
Metadata:
encoder : Lavc56.60.100 aac
Stream mapping:
Stream #0:0 -> #0:0 (mpeg2video (native) -> hevc (libx265))
Stream #0:1 -> #0:1 (mp2 (native) -> aac (native))
Press [q] to stop, [?] for help
mentre dentro a gambas si ferma (la codifica, l'applicazione risponde in modo fluido) dopo aver invocato ffmpeg. Sembra come se ffmpeg facesse partire un processo separato che pero' non va a buon fine :D
ps: nella consolle i gambas l'output di shell comando e' tipo questo:
FMain.RunEncoder.122: ffmpeg version 2.8.6-1ubuntu2 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 5.3.1 (Ubuntu 5.3.1-11ubuntu1) 20160311
configuration: --prefix=/usr --extra-version=1ubuntu2 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv
libavutil 54. 31.100 / 54. 31.100
libavcodec 56. 60.100 / 56. 60.100
libavformat 56. 40.101 / 56. 40.101
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 40.101 / 5. 40.101
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.101 / 1. 2.101
libpostproc 53. 3.100 / 53. 3.100
.... e non va oltre.
Ho anche provato ad inserire la creazione di un file di statistiche con l'opzione -vstats_file " & User.Home & "/MFRfile.txt "
nel comando di ffmpeg (che da terminale genera perfettamente tale file di statistica), ma dopo l'avvio del comando da "shell comando" (nell'applicativo gambas), del file di statistiche non c'e' ne e' traccia ...
AGGIORNAMENTO!
Quello pugnettoso (scusate il francesismo) sembrerebbe ffmpeg.
Utilzzando mencoder (che puo' utilizzare anche libac per la codifica, quindi ffmpeg sotto il cofano) shell comand
comando = "mencoder " & Encoded[0] & " -of mpeg -ovc lavc -lavcopts vcodec=mpeg1video -oac lavc -lavcopts acodec=mp2:abitrate=224 -o " & OutputFileName
Debug comando
Timer_Encode_status.Start
Shell (comando)
mi genera il file video transcodificato e mi ritorna in consolle il progresso dell'operazione:
...................
[mpeg1video @ 0x7f9ac08cc540]AVFrame.format is not set
[mpeg1video @ 0x7f9ac08cc540]AVFrame.width or height is not set
Pos: 913.2s 22830f (100%) 358.16fps Trem: 0min 112mb A-V:0.045 [795:224]
Skipping frame!
Pos: 913.2s 22831f (100%) 358.17fps Trem: 0min 112mb A-V:0.044 [795:224]
Flushing video frames.
Writing index...
Overhead: 1.305% (1518976 / 116396672)
Writing header...
Video stream: 795.951 kbit/s (99493 B/s) size: 90853772 bytes 913.160 secs 22831 frames
Audio stream: 224.000 kbit/s (28000 B/s) size: 25563552 bytes 912.984 secs
ora o risolvo direttamente con ffmpeg (che preferirei per evitare di dover avere 2 applicazioni nella macchina di deploy e per questioni di efficienza), OPPURE mi studio come passare gli stessi paramentri di ffmpeg attraverso mencoder :-(
Per il momento mi arrangio con questa modifica:
Public Sub RunEncoder()
Dim Encoded As String[] 'la lista delle path di tutti i file dalla sorgente da codificare
Dim I As Integer
Dim OutputFileName As String
'provo a farmi un file con tutti i singoli comandi ffmpeg da lanciare
Dim hFile As File
Dim comando As String
Encoded = FileChooser_Sorgente.SelectedPaths
'apre il file dello script per mettere il comando di codifica
hFile = Open FileChooser_Destinazione.Dir & "/long_script.sh" For Write Create
Do While Not ((bChiudo = True) Or (Encoded.count = 0)) 'fino a che non ho codificato tutti i file, oppure fino a quando non si preme "cancel"
OutputFileName = File.BaseName(Encoded[0])
OutputFileName = Replace(OutputFileName, " ", "_")
OutputFileName = FileChooser_Destinazione.Dir & "/" & OutputFileName & ".mkv"
'comando che in teoria dovrebbe andare bene con tanto di file delle stitistiche da spulciare per avere il progresso della codiifca
comando = "ffmpeg -i " & Encoded[0] & " -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k -strict -2 -vstats_file " & User.Home & "/MFRfile.txt " & OutputFileName
Print #hFile, comando
Sleep 0.1
'se la codifica e' andata bene allora lo rimuovo
Encoded.Remove(0)
Loop
'chiude il file dello script
Close #hFile
ToggleButton_encode.Value = 0
End
che in pratica genera il file di testo che con chmod +x trasformo in uno script da lanciare in un terminale.
Qui' tutto funziona .....
Appena ho tempo provero' a vedere come passare paramentri piu' complessi a mplayer (devo dare attravero mencoder il parametro -strict -2 a ffmpeg).
Sempre che non ho apito perche' ffmpeg diretta emnte mi manda a quel paese .....
Preliminarmente si potrebbe esperire una cosa analoga a questa:
' int Lancia_Comando(const char * comando)
' Chiama la libreria ad hoc per l'uso della funzione esterna "system()"
Private Extern Lancia_Comando(comando As String) As Integer In "/tmp/libadhoc"
Public Sub Main()
Dim s As String
Creaso()
s = "cvlc /percorso/file/audio"
Lancia_Comando(s)
End
Private Procedure Creaso()
File.Save("/tmp/libadhoc.c", "#include <stdlib.h>\n\n" &
"int Lancia_Comando(const char * comando) {\n\n" &
" system(comando);\n\n" &
" return (0);\n\n}")
Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -shared -fPIC" Wait
End
nella fretta m'era sfuggita questa tua perla ....
PERFETTO! FUNZIONA ALLA GRANDE.
(http://fialochka.rx22.ru/images/ranks/fialochka_rx22_ru/Laie_27.gif)
....e poi dicono che l'integrazione di più linguaggi non offre opportunità superiori. (http://forum.ubuntu-it.org/images/smilies/whistle.gif)
Ora mi faccio il parser del file di statistiche per eportare lo stato dell'operazione
Aspetta, non correre, per due motivi:
1) ......morirai stanco;
2) proviamo a "gambasizzare" un po' di più quel codice, effettuando una chiamata diretta della funzione esterna system( ) mediante Extern.
Il codice che devi provare, ora, è questo:
' int system(const char *__command)
' Execute the given line as a shell command.
Private Extern system_C(__command As String) As Integer In "libc:6" Exec "system"
Public Sub Main()
' Nel parametro va inserita - come stringa - la tua intera riga di comando con ffmpeg:
system_C("riga_di_comando")
End
..fammi sapere se così funziona.
ho leggermente modificato il ciclo di controllo dell'ultima riga (ora la penultima) del file delle statistiche di ffmpeg:
Public Sub Timer_Encode_status_Timer()
Dim UltimaRiga As String
Dim RigaPrecedente As String
Dim Riga As String
Dim fl As File
'magari semplicemente ffmpeg non ha ancora creato il file delle statistiche .... aspetto qualche ciclo
If Exist(FileChooser_Destinazione.Dir & "/MFRfile.txt") = False Then Return
'in questo caso il file esiste e inizio ad analizzarlo
fl = Open FileChooser_Destinazione.Dir & "/MFRfile.txt" For Read
' UltimaRiga = ""
' RigaPrecedente = ""
For Each Riga In fl.Lines
If InStr(riga, "?") > 0 Then RigaPrecedente = riga
Next
UltimaRiga = riga
'L'ultima lettura contiene i dati dell'ultima riga del file di testo (e se e' uguale a quella prima significa che ha finito):
If (RigaPrecedente <> "") And (Label_statistiche.Text = RigaPrecedente) Then
'ha finito la codifica di questo file e passa al prossimo
Timer_Encode_status.Stop
fl.Close
Else
Label_statistiche.Text = RigaPrecedente
fl.Close
Endif
End
questo perche' la riga VALIDA deve finire con un ? (non sono riuscito a fargli intercettare il CR o LF) mentre alle volte mi considerava l'operazione conclusa intercettando due righe (che sarebbero diventate diverse) che pero' erano entrambe 'frame = ' (ffmpeg non aveva ancora scritto il numero del frame processato .... che ovviamente incrementa).