2010-10-11 5 views
3

EDITUpdated code with solutionGStreamer transcode rapide

Je dois transcoder amr mp3, donc je l'ai écrit un pipeline dans GStreamer GStreamer-java. Il ressemble à ceci:

src ! amrparse ! amrnbdec ! lamemp3enc ! sink 

(en fait construit avec l'API java, bien sûr), je commence le transcoder avec

Bus.connect(EOS, fn(){Gst.quit();}); 

setState(PLAYING); 
Gst.main(); 

Il fonctionne très bien, sauf le temps qu'il faut est égale à l'audio longueur, ce qui n'est pas acceptable. L'équivalent

gst-launch 

transcode à la vitesse de la machine.

Alors, comment dois-je configurer le pipeline, pour obtenir le transcodage de la vitesse de la machine?

est ici la source complète, pour les personnes avec clojure couramment

(ns audio 
    (:import [org.gstreamer Gst Pipeline Bin Element ElementFactory State 
          StateChangeReturn Bus$EOS Bus$ERROR Bus$STATE_CHANGED] 
    [org.gstreamer.io InputStreamSrc OutputStreamSink] 
    [java.io InputStream OutputStream]) 
(:use clojure.contrib.logging)) 

(Gst/init) 
(defn transcode [^InputStream in ^OutputStream out] 
    (let [id (gensym (quote transcode)) 
     src (InputStreamSrc. in (str "in stream " id)) 
     dec0 (ElementFactory/make "amrparse" (str "amr parser " id)) 
     dec1 (ElementFactory/make "amrnbdec" (str "amr decoder " id)) 
     enc (doto (ElementFactory/make "lamemp3enc" (str "mp3 encoder " id)) 
       (.set "mono" true) 
       (.set "target" 0) 
       (.set "quality" 2)) 
     out (doto (OutputStreamSink. out (str "out stream " id)) 
       (.setSync false)) 
     pipe (doto (Pipeline. (str "transcoder pipe " id)) 
       (.add src) 
       (.add dec0) 
       (.add dec1) 
       (.add enc) 
       (.add out)) 
     clean (fn [] 
       (.setState src nil) 
       (.setState dec0 nil) 
       (.setState dec1 nil) 
       (.setState enc nil) 
       (.setState out nil) 
       (.setState pipe nil))] 
    (prn "starting transcode " id) 
    (.link src dec0) 
    (.link dec0 dec1) 
    (.link dec1 enc) 
    (.link enc out) 

    (doto (.getBus pipe) 
     (.connect 
     (reify Bus$EOS 
      (endOfStream [this src] 
      (prn "Bus finished " src) 
      (clean) 
      (Gst/quit)))) 
     (.connect 
     (reify Bus$ERROR 
      (errorMessage [this src code msg] 
      (prn "Bus Error " src code msg) 
      (clean) 
      (Gst/quit)))) 
     (.connect 
     (reify Bus$STATE_CHANGED 
      (stateChanged [this src old now pending] 
      (prn "Bus State change " src old now pending))))) 
    (.setState pipe State/PLAYING) 
    (Gst/main))) 

Répondre

6

Essayez .setSync(false) pour votre sortie. En gstreamer normal, un flux synchrone essaie de garder une trace de l'heure, tandis qu'un flux asynchrone va aussi vite que possible. Peut-être que votre flux de sortie essaie de fonctionner en temps réel.

+0

Parfait! C'était juste ce que je cherchais. Maintenant, je peux revenir sur le hack Shell Script :) Merci beaucoup! Pouvez-vous me dire où chercher cette information? Et pourquoi seulement le flux de sortie bloque, mais pas par ex. le flux d'entrée ou le pipeline lui-même? – Bendlas

+0

La sortie définit généralement le débit (la carte son) pour l'ensemble du pipeline. Pour quelque raison que ce soit, les bindings Java mettent cela à true, peut-être parce que c'est un flux io générique pas forcément un fichier, mais 'gst-launch ...! filesink' irait vite avec sync automatiquement false. Je ne sais pas où chercher ceci en plus de deviner à quoi servent les propriétés gst-inspect. – joeforker

Questions connexes