Hello,
Une petite astuce que l'on doit à Monsieur Müller (aka Zhorglub) et qui simplifie bien la vie.
Éléments requis:
- Une version de ffmpeg qui sache encoder le son en AAC
(soit on compile une version qui peut le faire, soit on a Feisty et on doit juste installer ffmpeg depuis synaptic ou adept, cf:
http://doc.ubuntu-fr.org/ffmpeg#ffmpeg_et_le_support_aac )
- python-gtk (dernière version tant qu'à faire)
1 on ouvre son éditeur (gedit, kate etc...) et on colle dans le fichier ce code:
#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-
##############################################
#
# avi2psp est une interface graphique pour convertir une vidéo
# .avi, .ogg, xvid, divx au format MP4 compatible avec la
# PlayStation Portable de Sony en invoquant ffmpeg
#
#
# Auteur: Dominique Müller (zhorglub CHEZ wanadoo POINT fr)
# Ce programme est soumis à la licence GNU/GPL v2
#
# Nécessite python 2.3 (ou supérieur)
# module pyGtk 2.4 (paquet Debian python-gtk2)
# ffmpeg (paquet Debian ffmpeg version CVS)
# convert (Image Magick) pour les thumbnails
#
# Capture video VLC (video4linux):
# aoss si vous devez utiliser un wrapper OSS pour ALSA
# (paquet Debian alsa-oss)
# VLC (http://www.videolan.org) Paquet Debian vlc
#
# Le script fonctionne avec knoppix 4/kaella 2.1 live-CD
# mais ffmpeg n'étant pas présent sur ces systèmes, il doit
# être installé manuellement
#
# Il peut y avoir des problèmes avec les noms de fichiers comportant
# des caractères accentués, si c'est votre cas:
# Faites dans une console:
#
# export G_FILENAME_ENCODING="iso-8859-1" (ou tout autre encodage)
#
# car gtk+ assume par défaut un encodage UTF-8
# Vous pouvez également rajouter cette ligne dans votre fichier
# ~/.bashrc pour qu'elle soit prise en compte au démarrage
# depuis le shell ou l'intégrer dans un script destiné à lancer
# le programme.
#
# Have fun :)
###############################################
import pygtk
pygtk.require('2.0')
import gtk
import os
import os.path
import gobject
class App:
def __init__(self):
self.wnd = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.wnd.set_title("Conversion Video PSP")
self.wnd.set_border_width(2)
self.basebox = gtk.VBox(False, 0)
self.box0 = gtk.HBox(False, 0)
self.progressbox = gtk.HBox(False, 0)
self.wnd.add(self.basebox)
self.box1 = gtk.VBox(False, 0)
self.box2 = gtk.VBox(False, 0)
self.box3 = gtk.HBox(False, 0)
self.box4 = gtk.HBox(False, 0)
self.boxlabel = gtk.VBox(False, 0)
self.boxradio = gtk.VBox(False, 0)
self.boxlbl2 = gtk.VBox(True, 0)
self.boxlbl3 = gtk.VBox(True, 0)
self.comboboxes = gtk.VBox(False, 0)
self.menu_items = (
( "/_Options", None, None, 0, "<Branch>" ),
( "/Options/Capturer une video avec _VLC (video4linux)", "<control>V", self.capture_video, 0, '<StockItem>', gtk.STOCK_NEW ),
( "/Options/_Parametres de capture VLC", "<control>P", self.capture_param, 0, '<StockItem>', gtk.STOCK_PREFERENCES ),
( "/Options/_Copier la commande vers le presse-papier", "<control>C", self.copy_to_clipboard, 0, '<StockItem>', gtk.STOCK_COPY ),
( "/Options/Source audio _WAV", "<control>W", self.remux_video, 0, '<StockItem>', gtk.STOCK_JUMP_TO ),
( "/Options/sep1", None, None, 0, "<Separator>" ),
( "/Options/_Quitter", "<control>Q", gtk.main_quit, 0, '<StockItem>', gtk.STOCK_QUIT ),
)
self.menubar = self.get_main_menu(self.wnd)
self.basebox.pack_start(self.menubar, False, False, 0)
self.menubar.show()
self.clipboard = gtk.clipboard_get("CLIPBOARD")
self.copy_sel = False # Par défaut: exécution de la commande
# Variables globales par défaut
self.smono = "2" # Par défaut le son est en stéréo
self.extrn_wav = '' # Fichier son externe .wav
self.capt_file = 'capture.avi'
self.default_video_device = '/dev/video0'
self.default_audio_device = '/dev/dsp0'
self.aoss_chk = False
self.std_val = 'SECAM'
self.chn_val = 0
# Si le fichier ./.avi2psprc existe, on récupère les valeurs
# sinon --> valeurs par défaut
f = "./.avi2psprc"
if os.access(f, os.F_OK):
h = open(f, 'r')
null_input = h.readline()
self.capt_file = h.readline()
self.capt_file = self.capt_file[:-1]
self.default_video_device = h.readline()
self.default_video_device = self.default_video_device[:-1]
self.default_audio_device = h.readline()
self.default_audio_device = self.default_audio_device[:-1]
tmp = h.readline()
if tmp[:-1] == 'True':
self.aoss_chk = True
else:
self.aoss_chk = False
self.std_val = h.readline()
self.std_val = self.std_val[:-1]
self.chn_val = int(h.readline())
h.close()
# Labels
lsource = gtk.Label("Source: ")
self.boxlabel.pack_start(lsource, True, True, 0)
lsource.show()
ldest = gtk.Label(" Destination: ")
self.boxlabel.pack_end(ldest, True, True, 0)
ldest.show()
laudiobr = gtk.Label("Audio: ")
self.boxlbl2.pack_start(laudiobr, True, True, 0)
laudiobr.show()
lvideobr = gtk.Label("Video: ")
self.boxlbl2.pack_start(lvideobr, True, True, 0)
lvideobr.show()
laudiobr = gtk.Label(" Kbps")
self.boxlbl3.pack_start(laudiobr, True, True, 0)
laudiobr.show()
lvideobr = gtk.Label(" Kbps")
self.boxlbl3.pack_start(lvideobr, True, True, 0)
lvideobr.show()
lcodec = gtk.Label("Codec:")
self.boxlbl2.pack_start(lcodec, True, True, 0)
lcodec.show()
lcodec = gtk.Label("")
self.boxlbl3.pack_start(lcodec, True, True, 0)
lcodec.show()
# Entries
self.source = gtk.Entry(max=0)
self.box1.pack_start(self.source, True, True, 0)
infobulles = gtk.Tooltips()
infobulles.set_tip(self.source, "Entrez ou selectionnez le nom du fichier a convertir\nSi vous voulez utiliser deux fichiers separes\npour l'audio et la video, indiquez le fichier video ici\net faites Options --> Source audio WAV pour selectionner l'audio")
separator = gtk.HSeparator()
self.box1.pack_start(separator, False, True, 5)
separator.show()
self.dest = gtk.Entry(max=0)
self.dest.set_text("M4V00001.MP4")
self.box1.pack_start(self.dest, True, True, 0)
# Checkbox mono/stéréo
laud = gtk.Label(" Audio: ")
self.box3.pack_start(laud, False, False, 0)
laud.show()
self.mono = gtk.CheckButton(" Mono ")
self.box3.pack_start(self.mono, False, False, 2)
self.mono.show()
self.mono.connect("toggled", self.set_mono, None)
# Checkbox audio/copie
self.acopy = gtk.CheckButton(" Copy ")
self.box3.pack_start(self.acopy, False, False, 2)
self.acopy.show()
infobulles = gtk.Tooltips()
infobulles.set_tip(self.acopy, "Copier l'audio sans reencodage")
separator1 = gtk.VSeparator()
self.box3.pack_start(separator1, False, True, 5)
separator1.show()
# Spin volume +
self.vol_adj = gtk.Adjustment(0.0, 0.0, 300.0, 5.0, 1.0, 0.0)
self.vol_spin = gtk.SpinButton(self.vol_adj, 0, 0)
lvol = gtk.Label(" Volume + ")
self.box3.pack_start(lvol, False, False, 0)
lvol.show()
self.box3.pack_start(self.vol_spin, False, False, 0)
self.vol_spin.show()
infobulles = gtk.Tooltips()
infobulles.set_tip(self.vol_spin, "Augmente le volume de la piste audio de n %\nUne valeur trop elevee peut alterer la qualite sonore\ndu projet et causer des dommages auditifs importants\nA utiliser avec moderation! (Max: 300 %)\nInactif si l'option copy est selectionnee ")
lvol = gtk.Label(" % ")
self.box3.pack_start(lvol, False, False, 0)
lvol.show()
# Cropping
separator1 = gtk.VSeparator()
self.box3.pack_start(separator1, False, True, 5)
separator1.show()
self.adj2 = gtk.Adjustment(0.0, 0.0, 100.0, 2.0, 1.0, 0.0)
self.cropbottom = gtk.SpinButton(self.adj2, 0, 0)
self.cropbottom.set_wrap(True)
self.box3.pack_end(self.cropbottom, False, False, 5)
self.cropbottom.show()
lcb = gtk.Label(" Bas:")
self.box3.pack_end(lcb, False, False, 5)
lcb.show()
self.adj = gtk.Adjustment(0.0, 0.0, 100.0, 2.0, 1.0, 0.0)
self.croptop = gtk.SpinButton(self.adj, 0, 0)
self.croptop.set_wrap(True)
self.box3.pack_end(self.croptop, False, True, 5)
self.croptop.show()
lct = gtk.Label(" Cropping: Haut:")
self.box3.pack_end(lct, False, False, 5)
lct.show()
# Thumbnail
lthmb = gtk.Label(" Creer thumbnail (icone) a la position : ")
self.box4.pack_start(lthmb, False, False, 0)
lthmb.show()
# Spins h:m:s --> Minutes
self.hms2 = gtk.Adjustment(0.0, 0.0, 15.0, 1.0, 1.0, 0.0)
self.minute = gtk.SpinButton(self.hms2, 0, 0)
self.minute.set_wrap(True)
self.box4.pack_start(self.minute, False, True, 5)
self.minute.show()
lthmb = gtk.Label(" min ")
self.box4.pack_start(lthmb, False, False, 0)
lthmb.show()
# Spins h:m:s --> Secondes
self.hms3 = gtk.Adjustment(0.0, 0.0, 59.0, 1.0, 1.0, 0.0)
self.seconde = gtk.SpinButton(self.hms3, 0, 0)
self.seconde.set_wrap(True)
self.box4.pack_start(self.seconde, False, True, 5)
self.seconde.show()
lthmb = gtk.Label(" sec ")
self.box4.pack_start(lthmb, False, False, 0)
lthmb.show()
# Boutons
self.thumb = gtk.Button(" Creer ")
self.box4.pack_end(self.thumb, True, False, 0)
self.thumb.connect("clicked", self.create_thumbnail, None)
self.thumb.show()
self.choix_src = gtk.Button()
self.choix_src.connect("clicked", self.select_src, None)
boxb2 = xpm_label_box(self.wnd, "info.xpm")
self.choix_src.add(boxb2)
boxb2.show()
self.box2.pack_start(self.choix_src, True, False, 0)
separator1 = gtk.HSeparator()
self.box2.pack_start(separator1, False, True, 5)
separator1.show()
self.choix_dest = gtk.Button()
self.choix_dest.connect("clicked", self.select_dest, None)
boxb1 = xpm_label_box(self.wnd, "info.xpm")
self.choix_dest.add(boxb1)
boxb1.show()
self.box2.pack_start(self.choix_dest, True, False, 0)
self.makeItSo = gtk.Button(None, gtk.STOCK_OK)
self.makeItSo.connect("clicked", self.exec_comm)
# Boutons radios
self.radio = gtk.RadioButton(None, "320x240")
self.radio.connect("toggled", self.res_set, "320x240")
self.radio.set_active(True)
self.boxradio.pack_start(self.radio, True, True, 5)
self.radio.show()
self.resolution = "320x240" # résolution par défaut
self.radio = gtk.RadioButton(self.radio, "368x208")
self.radio.connect("toggled", self.res_set, "368x208")
self.boxradio.pack_start(self.radio, True, True, 5)
self.radio.show()
self.radio = gtk.RadioButton(self.radio, "400x192")
self.radio.connect("toggled", self.res_set, "400x192")
self.boxradio.pack_start(self.radio, True, True, 5)
self.radio.show()
self.radio = gtk.RadioButton(self.radio, "Original")
self.radio.connect("toggled", self.res_set, "0")
self.boxradio.pack_start(self.radio, True, True, 5)
self.radio.show()
# Comboboxes
self.audiobr = gtk.combo_box_new_text()
self.videobr = gtk.combo_box_new_text()
self.codec = gtk.combo_box_new_text()
self.codec.append_text('h264/AVC')
self.codec.append_text('xvid')
self.codec.append_text('mpeg4')
self.codec.append_text('copy')
self.audiobr.append_text('128')
self.audiobr.append_text('64')
self.audiobr.append_text('48')
self.audiobr.append_text('32')
self.audiobr.append_text('16')
self.videobr.append_text('768')
self.videobr.append_text('512')
self.videobr.append_text('384')
self.videobr.set_active(1)
self.audiobr.set_active(3)
self.codec.set_active(0)
self.comboboxes.pack_start(self.audiobr, True, False, 0)
self.comboboxes.pack_end(self.codec, True, False, 0)
self.comboboxes.pack_end(self.videobr, True, False, 0)
self.audiobr.show()
self.videobr.show()
self.codec.show()
# Barre de progression
self.plabel = gtk.Label("Etat: ")
self.progressbox.pack_start(self.plabel, False, False, 0)
self.plabel.show()
self.pbar = gtk.ProgressBar(None)
self.pbar.set_text('Conversion en attente')
#self.pbar.set_fraction(0.62)
self.pbar.show()
self.progressbox.pack_start(self.pbar, True, True, 20)
# Pack général
self.box0.pack_start(self.boxlabel, False, False, 0)
self.box0.pack_start(self.box1, False, False, 0)
self.box0.pack_start(self.box2, False, False, 0)
self.box0.pack_start(self.boxradio, False, False, 20)
self.box0.pack_start(self.boxlbl2, False, False, 10)
self.box0.pack_start(self.comboboxes, False, False, 0)
self.box0.pack_start(self.boxlbl3, False, False, 10)
self.box0.pack_end(self.makeItSo, True, True, 0)
self.basebox.pack_start(self.box0, False, False, 0)
separator2 = gtk.HSeparator()
self.basebox.pack_start(separator2, False, True, 5)
separator2.show()
self.basebox.pack_start(self.box3, False, False, 0)
separator3 = gtk.HSeparator()
self.basebox.pack_start(separator3, False, True, 5)
separator3.show()
self.basebox.pack_start(self.box4, False, False, 0)
separator4 = gtk.HSeparator()
self.basebox.pack_start(separator4, False, True, 5)
separator4.show()
self.basebox.pack_start(self.progressbox, False, False, 10)
self.source.show()
self.dest.show()
self.choix_src.show()
self.choix_dest.show()
self.makeItSo.show()
self.progressbox.show()
self.basebox.show()
self.box0.show()
self.boxlabel.show()
self.box1.show()
self.box2.show()
self.box3.show()
self.box4.show()
self.boxradio.show()
self.boxlbl2.show()
self.comboboxes.show()
self.boxlbl3.show()
self.wnd.show()
return
# Bon, celle-là, c'est du copier/coller depuis la doc de pyGtk, qu'ils en soient remerciés..
def get_main_menu(self, window):
accel_group = gtk.AccelGroup()
# This function initializes the item factory.
# Param 1: The type of menu - can be MenuBar, Menu,
# or OptionMenu.
# Param 2: The path of the menu.
# Param 3: A reference to an AccelGroup. The item factory sets up
# the accelerator table while generating menus.
item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group)
# This method generates the menu items. Pass to the item factory
# the list of menu items
item_factory.create_items(self.menu_items)
# Attach the new accelerator group to the window.
window.add_accel_group(accel_group)
# need to keep a reference to item_factory to prevent its destruction
self.item_factory = item_factory
# Finally, return the actual menu bar created by the item factory.
return item_factory.get_widget("<main>")
def select_src(self, w, d):
self.filew = gtk.FileSelection("Choisir le fichier source")
self.filew.ok_button.connect("clicked", self.file_ok_sel)
self.filew.cancel_button.connect("clicked", self.file_cn_sel)
self.filew.show()
return
def select_wav(self, w, d):
self.filew = gtk.FileSelection("Choisir le fichier source audio")
self.filew.ok_button.connect("clicked", self.wav_ok_sel)
self.filew.cancel_button.connect("clicked", self.file_cn_sel)
self.filew.show()
return
def select_dest(self, w, d):
self.filew = gtk.FileSelection("Choisir le fichier destination")
self.filew.ok_button.connect("clicked", self.file_ok_seld)
self.filew.cancel_button.connect("clicked", self.file_cn_sel)
self.filew.set_filename(self.dest.get_text())
self.filew.show()
return
def file_ok_sel(self, w):
self.source.set_text(self.filew.get_filename())
self.filew.destroy()
return
def wav_ok_sel(self, w):
self.source_wav.set_text(self.filew.get_filename())
self.filew.destroy()
return
def file_ok_seld(self, w):
self.dest.set_text(self.filew.get_filename())
self.filew.destroy()
return
def file_cn_sel(self, w):
self.filew.destroy()
return
def res_set(self, w, data):
self.resolution = data
return
def get_active_text(self, combobox):
model = combobox.get_model()
active = combobox.get_active()
if active < 0:
return None
return model[active][0]
def create_thumbnail(self, w, d):
cm = self.minute.get_value_as_int()
cs = self.seconde.get_value_as_int()
ct = str(cs + (cm * 60))
dst = self.dest.get_text()
dst = dst[:-3] + "gif" # remplacer "gif" par "THM" si encodage direct
ccmd = "ffmpeg -y -i " + self.source.get_text() + " -ss " + ct + " -f gif -vframes 1 -s 160x120 -an " + dst # remplacer "-f gif" par "-f singlejpeg" si encodage direct
o = os.system(ccmd)
if os.access(dst, os.F_OK): # Conserver cette ligne
ccmd = "convert " + dst + " " + dst[:-3] + "jpg" # Peut-être supprimée si jpeg direct
o = os.system(ccmd) # idem
if os.access(dst[:-3]+'jpg', os.F_OK): # idem
ccmd = "rm -f " + dst + "\n" # idem
ccmd = ccmd + "mv " + dst[:-3] + "jpg " + dst[:-3] + "THM" # idem
dst = dst[:-3] + "THM" # idem
o = os.system(ccmd) # idem
self.pbar.set_text('Creation de l\'icone '+dst+' a '+ ct +' secondes : complete') # supprimer 1 indentation (tab) mais conserver la ligne
else: # supprimer
self.pbar.set_text('La creation de l\'icone a echoue!') # supprimer
else:
self.pbar.set_text('La creation de l\'icone a echoue!')
# Commande utilisée: ffmpeg -y -i videofile.avi -f gif -ss value -vframes 1 -s 160x120 -an M4VXXXXX.THM
#
# Explication de cette bizarrerie --> -f gif:
# Sur ma version de ffmpeg je n'ai accès qu'au format gif pour les images, j'encode donc en GIF puis j'utilise
# convert file.gif file.jpg pour mettre le fichier en jpeg. Cela suppose et implique d'avoir installé Image magick
# sur votre système. Toutefois, si vous avez une version de ffmpeg qui encode directement en jpeg, vous pouvez
# sans risque modifier les lignes ci-dessus pour simplifier tout ça!!
# Ne m'en veuillez pas, je sais que gif n'est pas un format libre et que ça n'est pas bien, même pour
# un fichier temporaire... ;p
return
def exec_comm(self, w):
#
name = os.path.basename(os.path.splitext(self.source.get_text())[0])
ccmd = "ffmpeg -y -i " + self.source.get_text() + self.extrn_wav + " -title " + name
ccmd = ccmd + " -vcodec "
if self.get_active_text(self.codec) != 'copy':
if self.get_active_text(self.codec) == 'h264/AVC':
ccmd = ccmd + "h264 -level 13 -g 250"
else:
ccmd = ccmd + self.get_active_text(self.codec)
if self.get_active_text(self.audiobr) == '128':
self.audiobr.set_active(1) # Pour les vidéos 'non-h264', le bitrate audio ne doit pas dépasser 64 kbits
# Ceci corrige une éventuelle saisie erronée en mettant la valeur à 64 kbps
if self.resolution != "0":
ccmd = ccmd + " -s " + self.resolution
ccmd = ccmd + " -r 29.97 -b " + self.get_active_text(self.videobr)
ct = self.croptop.get_value_as_int()
cb = self.cropbottom.get_value_as_int()
if ct != 0:
ccmd = ccmd + " -croptop " + str(ct)
if cb != 0:
ccmd = ccmd + " -cropbottom " + str(cb)
else:
ccmd = ccmd + "copy"
if self.acopy.get_active():
ccmd = ccmd + " -acodec copy"
else:
ccmd = ccmd + " -acodec aac"
if self.vol_spin.get_value_as_int() > 0:
ccmd = ccmd + " -vol " + str(self.vol_spin.get_value_as_int())
ccmd = ccmd + " -ac " + self.smono + " -ar 24000 -ab " + self.get_active_text(self.audiobr)
if self.get_active_text(self.codec) != 'h264/AVC':
ccmd = ccmd + " -f psp "
else:
ccmd = ccmd + " "
ccmd = ccmd + self.dest.get_text()
print ccmd
if self.copy_sel:
if not self.clipboard.set_text(ccmd, -1):
self.pbar.set_text('Copie de la commande ffmpg vers le presse-papier: complete')
self.copy_sel = False
else:
self.pbar.set_text('La commande ne peut pas etre copiee: Echec !')
else:
if os.access(self.dest.get_text(), os.F_OK):
if self.ask_ok_cancel("Fichier existant", "\nUn fichier avec le meme nom existe deja.\n\n Ecraser ?\n") == 1:
o = os.system('xterm -e ' + ccmd + " &")
self.t1 = gobject.timeout_add(3000, self.gimmick)
self.t2 = gobject.timeout_add(100, self.gimmick2)
self.t3 = gobject.timeout_add(4000, self.ffmpeg_activity)
else:
o = os.system('xterm -e ' + ccmd + " &")
self.t1 = gobject.timeout_add(3000, self.gimmick)
self.t2 = gobject.timeout_add(100, self.gimmick2)
self.t3 = gobject.timeout_add(4000, self.ffmpeg_activity)
return
def remux_video(self, w, d):
self.dialog = gtk.Dialog("Selection Fichier Wav", self.wnd, gtk.DIALOG_DESTROY_WITH_PARENT, None)
hbox = gtk.HBox(False, 0)
self.dialog.vbox.pack_start(hbox, True, True, 0)
label = gtk.Label(" Fichier : ")
hbox.pack_start(label, True, True, 0)
label.show()
self.source_wav = gtk.Entry(max=0)
self.source_wav.set_text(self.extrn_wav)
hbox.pack_start(self.source_wav, False, True, 5)
self.source_wav.show()
infobulles = gtk.Tooltips()
infobulles.set_tip(self.source_wav, "Le fichier indique sera pris comme source audio\nlors de l'encodage.\nTous les formats audio supportes par ffmpeg sont valides")
self.choix_wav = gtk.Button()
self.choix_wav.connect("clicked", self.select_wav, None)
box2 = xpm_label_box(self.dialog, "info.xpm")
self.choix_wav.add(box2)
box2.show()
hbox.pack_start(self.choix_wav, True, False, 0)
self.choix_wav.show()
makeItSo_cancel = gtk.Button(None, gtk.STOCK_CANCEL)
makeItSo_cancel.connect("clicked", self.dialogdestroy)
self.dialog.action_area.pack_start(makeItSo_cancel, False, True, 0)
makeItSo_cancel.show()
makeItSo_ok = gtk.Button(None, gtk.STOCK_OK)
makeItSo_ok.connect("clicked", self.set_Ok_destroy)
self.dialog.action_area.pack_end(makeItSo_ok, False, True, 0)
makeItSo_ok.show()
hbox.show()
self.dialog.show()
return
def set_Ok_destroy(self, w):
if self.source_wav.get_text() == '':
self.extrn_wav = ''
else:
self.extrn_wav = " -i " + self.source_wav.get_text()
self.dialog.destroy()
return
def capture_video(self, w, d):
#os.system('/home/zhorglub/video_grab &')
ccmd = ''
if self.aoss_chk:
ccmd = ccmd + 'aoss '
ccmd = ccmd + 'vlc v4l:// :v4l-vdev="' + self.default_video_device + '" :v4l-adev="' + self.default_audio_device + '" :v4l-norm='
if self.std_val == 'SECAM':
ccmd = ccmd + '2 :v4l-channel='
elif self.std_val == 'PAL':
ccmd = ccmd + '0 :v4l-channel='
elif self.std_val == 'NTSC':
ccmd = ccmd + '1 :v4l-channel='
else:
ccmd = ccmd + '2 :v4l-channel='
ccmd = ccmd + str(self.chn_val)
ccmd = ccmd + " :v4l-frequency=-1 --sout \'#transcode{vcodec=mp4v,vb=2048,scale=1}:duplicate{dst=std{access=file,mux=asf,url=\""
ccmd = ccmd + self.capt_file + "\"}}' &"
print "Commande pour la capture VLC:\n"
print ccmd
os.system(ccmd)
return
def capture_param(self, w, d):
self.dialog = gtk.Dialog("Parametres de capture VLC", self.wnd, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, None)
string = """ Vous pouvez modifier ici les parametres par defaut fournis
au programme VLC.
Pour en savoir plus sur VLC: http://www.videolan.org
La capture utilise les parametres suivants:
Codec video: mp4v 2048 kbps 25 fps
Audio: s16le (PCM 44100 Hz 16 bits)
Container: asf
"""
label = gtk.Label(string)
self.dialog.vbox.pack_start(label, False, True, 10)
label.show()
hbox = gtk.HBox(False, 0) # /dev/video /dev/dsp
hbox2 = gtk.HBox(False, 0) # aoss checkbox
hbox3 = gtk.HBox(False, 0) # Entry fichier capture par défaut
hbox4 = gtk.HBox(False, 0) # standard + canal
label = gtk.Label(" Video ")
hbox.pack_start(label, False, True, 0)
label.show()
self.devv = gtk.Entry(max=0)
self.devv.set_text(self.default_video_device)
hbox.pack_start(self.devv, False, True, 0)
self.devv.show()
self.deva = gtk.Entry(max=0)
self.deva.set_text(self.default_audio_device)
hbox.pack_end(self.deva, False, True, 5)
self.deva.show()
label = gtk.Label(" Audio ")
hbox.pack_end(label, False, True, 0)
label.show()
self.aoss = gtk.CheckButton("Utiliser aoss (Wrapper OSS pour ALSA)")
hbox2.pack_start(self.aoss, False, False, 2)
self.aoss.set_active(self.aoss_chk)
self.aoss.show()
label = gtk.Label(" Fichier de capture: ")
hbox3.pack_start(label, True, True, 0)
label.show()
self.capt = gtk.Entry(max=0)
self.capt.set_text(self.capt_file)
hbox3.pack_start(self.capt, False, True, 5)
self.capt.show()
label = gtk.Label(" Standard: ")
hbox4.pack_start(label, True, True, 0)
label.show()
self.standard = gtk.combo_box_new_text()
self.channel = gtk.combo_box_new_text()
self.standard.append_text('PAL')
self.standard.append_text('SECAM')
self.standard.append_text('NTSC')
if self.std_val == 'SECAM':
self.standard.set_active(1)
elif self.std_val == 'PAL':
self.standard.set_active(0)
elif self.std_val == 'NTSC':
self.standard.set_active(2)
else:
self.standard.set_active(1)
hbox4.pack_start(self.standard, False, True, 0)
self.standard.show()
self.channel.append_text('TV')
self.channel.append_text('Composite')
self.channel.append_text('S-Video')
self.channel.set_active(self.chn_val)
hbox4.pack_end(self.channel, False, True, 0)
self.channel.show()
label = gtk.Label(" Canal: ")
hbox4.pack_end(label, True, True, 0)
label.show()
self.dialog.vbox.pack_start(hbox, True, True, 10)
self.dialog.vbox.pack_start(hbox2, True, True, 10)
self.dialog.vbox.pack_start(hbox3, True, True, 10)
self.dialog.vbox.pack_start(hbox4, True, True, 10)
makeItSo_cancel = gtk.Button(None, gtk.STOCK_CANCEL)
makeItSo_cancel.connect("clicked", self.dialogdestroy)
self.dialog.action_area.pack_start(makeItSo_cancel, True, False, 0)
makeItSo_cancel.show()
makeItSo_ok = gtk.Button(None, gtk.STOCK_SAVE)
makeItSo_ok.connect("clicked", self.set_saveconfig_destroy)
self.dialog.action_area.pack_end(makeItSo_ok, False, True, 0)
makeItSo_ok.show()
infobulles = gtk.Tooltips()
infobulles.set_tip(makeItSo_ok, "Valider et sauvegarder pour les sessions ulterieures")
makeItSo_valid = gtk.Button(None, gtk.STOCK_OK)
makeItSo_valid.connect("clicked", self.set_valid_destroy)
self.dialog.action_area.pack_end(makeItSo_valid, False, True, 0)
makeItSo_valid.show()
infobulles = gtk.Tooltips()
infobulles.set_tip(makeItSo_valid, "Valider uniquement pour cette session (pas de sauvegarde)")
hbox.show()
hbox2.show()
hbox3.show()
hbox4.show()
self.dialog.show()
return
def set_saveconfig_destroy(self, w):
self.capt_file = self.capt.get_text()
self.default_video_device = self.devv.get_text()
self.default_audio_device = self.deva.get_text()
self.aoss_chk = self.aoss.get_active()
self.std_val = self.standard.get_active_text()
self.chn_val = self.channel.get_active()
self.dialog.destroy()
f=open('./.avi2psprc', 'w')
f.write("# N'éditez pas ce fichier manuellement, utilisez le menu Options --> Paramètres de capture\n")
f.write(self.capt_file + "\n")
f.write(self.default_video_device + "\n")
f.write(self.default_audio_device + "\n")
f.write(str(self.aoss_chk) + "\n")
f.write(self.std_val + "\n")
f.write(str(self.chn_val) + "\n")
f.close()
return
def set_valid_destroy(self, w):
self.capt_file = self.capt.get_text()
self.default_video_device = self.devv.get_text()
self.default_audio_device = self.deva.get_text()
self.aoss_chk = self.aoss.get_active()
self.std_val = self.standard.get_active_text()
self.chn_val = self.channel.get_active()
self.dialog.destroy()
return
def copy_to_clipboard(self, w, d):
self.copy_sel = True
self.exec_comm(w)
return
def set_mono(self, w, data):
if w.get_active():
self.smono = "1"
else:
self.smono = "2"
return
def gimmick(self):
self.pbar.set_pulse_step(0.05)
self.pbar.pulse()
gobject.source_remove(self.t1)
self.t1 = gobject.timeout_add(50, self.gimmick)
return
def gimmick2(self):
self.pbar.set_text('Encodage en cours')
return True
def ask_ok_cancel(self, title, string):
self.val = 0
self.dialog = gtk.Dialog(title, self.wnd, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, None)
label = gtk.Label(string)
self.dialog.vbox.pack_start(label, True, True, 0)
label.show()
makeItSo_cancel = gtk.Button(None, gtk.STOCK_CANCEL)
makeItSo_cancel.connect("clicked", self.dialogdestroy)
self.dialog.action_area.pack_start(makeItSo_cancel, True, True, 0)
makeItSo_cancel.show()
makeItSo_ok = gtk.Button(None, gtk.STOCK_OK)
makeItSo_ok.connect("clicked", self.setvaltrue)
self.dialog.action_area.pack_end(makeItSo_ok, True, True, 0)
makeItSo_ok.show()
self.dialog.run()
return self.val
def setvaltrue(self, w):
self.val = 1
self.dialog.destroy()
return
def dialogdestroy(self, w):
self.val = 2
self.dialog.destroy()
return
def ffmpeg_activity(self):
o = os.popen('ps -C ffmpeg')
s = None
l = 0
while s != '':
ts = len(o.readline())
if ts != 0:
l = l + 1
else:
break
o.close()
if l == 1:
gobject.source_remove(self.t1)
gobject.source_remove(self.t2)
gobject.source_remove(self.t3)
self.pbar.set_fraction(0.0)
self.pbar.set_text('Fin de la conversion')
return True
# Remerciement: La fonction suivante provient de l'exemple buttons.py dans la doc pyGtk2.4
# et a été adaptée pour ce programme
def xpm_label_box(parent, xpm_filename):
# Create box for xpm and label
box1 = gtk.HBox(False, 0)
box1.set_border_width(2)
# Now on to the image stuff
image = gtk.Image()
image.set_from_file(xpm_filename)
# Pack the pixmap and label into the box
box1.pack_start(image, False, False, 3)
image.show()
return box1
def main():
gtk.main()
if __name__ == "__main__":
root = App()
main()
2 on sauvegarde ce fichier que l'on nommera avi2psp.py dans le répertoire de son choix.
3 on teste si tout fonctionne bien via la console par la commande :
python /chemindufichier/avi2psp.py
4 on découvre cette interface fort sympathique :
5 il ne reste plus qu'à créer un raccourci dans votre tableau de bord pour que la chose soit absolument conviviale.
6 pour en savoir un peu plus et se tenir au courant d'éventuelles mises à jours du code en fonction des avancées d'ffmpeg par exemple, rendez vous de temps à autre par ici:
http://forums.knoppix-fr.org/viewtopic.php?pid=66892
Bon films ! 🙂