Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Interface de Voz con Rails

2,567 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Interface de Voz con Rails

  1. 1. RoR puede también hablar: Interface de voz con Rails Svet Ivantchev, eFaber svet@efaber.net 22 de noviembre de 2007, ConferenciaRails 2007, Madrid
  2. 2. ¿Qué es VoIP?
  3. 3. Ejemplos ... y 1000s más
  4. 4. ¿Es por dinero? • Ok, las llamadas VoIP son baratas pero no eso es importante • Flexibilidad y integración con aplicaciones
  5. 5. Demo • Consulta de notas por web • Consulta de notas por teléfono La voz es una interface más
  6. 6. ¿Por qué ahora? • Web stack (ej: SO, BD, RoR :-)) • VoIP (ej: Asterisk) • Ancho de banda • Los IVR dejan mucho que desear
  7. 7. Asterisk (conceptos) http://asterisk.org • Centralita Open Source (PBX) • Protocolos: SIP, IAX • Proveedores
  8. 8. Componentes Clientes VoIP DID SIP, IAX SIP, IAX SIP, IAX ZAP Red PSTN Terminación
  9. 9. Asterisk (instalación) compilamos: $ wget http://downloads.digium.com/pub/ asterisk/releases/asterisk-1.4.13.tar.gz $ tar zxvf asterisk-1.4.13.tar.gz $ cd asterisk-1.4.13 $ ./configure $ make menuselect $ make $ sudo make install $ sudo make samples comprobamos: $ sudo asterisk -vvvvvc voces en castellano: http://www.voipnovatos.es
  10. 10. Asterisk (config) en /etc/asterisk/sip.conf [pb15] [spa941] context=demo1 context=demo1 type=friend type=friend secret=sekreto42 secret=otrapassw host=dynamic host=dynamic canreinvite=no canreinvite=no en /etc/asterisk/extensions.conf [demo1] exten => 101,1,Dial(SIP/pb15) exten => 102,1,Dial(SIP/spa941)
  11. 11. Cliente softphone
  12. 12. Cliente hardware
  13. 13. Números públicos
  14. 14. DID y SIP URI
  15. 15. Demo • Llamada entre dos números • Con el número público
  16. 16. Ideas • Respuesta diferente por horas • Respuesta diferente en función del CallerID • Integración con Jabber • Voicemail • IVR, colas • 1000s de cosas mas ...
  17. 17. El dialplan se complica [efmenu] include => users5xx include => rooms include => efhq exten => s,1,NoOp(Entering eF main menu for caller ${CALLERID}) exten => s,2,Answer exten => s,3,Wait(2) exten => s,4,Playback(beep) exten => s,5,Background(${SALUDOEN}enter-ext-of-person) exten => s,6,Background(beep) exten => s,7,WaitExten(15) exten => 101,1,Playback(room-service) exten => 101,2,Goto(efmenu,s,4) exten => 999,1,Goto(svetdisa,s,1) exten => 999,2,Goto(efmenu,s,4) exten => i,1,Playback(pbx-invalid) exten => i,2,Goto(efmenu,s,6) exten => t,1,Playback(vm-goodbye) exten => t,2,Hangup()
  18. 18. ...y se hace feo exten => 508,1,Macro(voicemail,SIP/esti) exten => 509,1,Macro(voicemail,SIP/kolio) exten => 510,1,Macro(voicemail,SIP/jean) exten => 511,1,Macro(voicemail,SIP/ruben) exten => 512,1,Macro(voicemail,SIP/inaki) [macro-voicemail] exten => s,1,Dial(${ARG1},30) exten => s,2,Goto(s-${DIALSTATUS},1) exten => s-NOANSWER,1,Voicemail(u${MACRO_EXTEN}) exten => s-NOANSWER,n,Hangup() exten => s-CHANUNAVAIL,1,Playback(unavailable) exten => s-CHANUNAVAIL,n,Hangup() exten => s-CONGESTION,1,Busy(5) exten => s-CONGESTION,n,Hangup() exten => s-BUSY,1,Voicemail(b${MACRO_EXTEN}) exten => s-BUSY,n,Hangup() exten => _s-.,1,Goto(s-NOANSWER,1)
  19. 19. AGI y AMI • Asterisk Gateway Interface • Asterisk Manager Interface
  20. 20. Alternativas • Adhearsion • Telegraph
  21. 21. Adhearsion http://adhearsion.com • El dialplan escrito en Ruby • ActiveRecord integrado • Integración con Rails • versiones (0.7.7 vs 0.8)
  22. 22. Adhearsion 1: Hello World $ sudo gem install adhearsion $ ahn create hello1 Creating /Users/svet/hello1/config/adhearsion.sqlite3 Creating /Users/svet/hello1/config/adhearsion.yml Creating /Users/svet/hello1/config/database.rb Creating /Users/svet/hello1/config/database.yml Creating /Users/svet/hello1/config/helpers/drb_server.yml Creating /Users/svet/hello1/config/helpers/factorial.alien.c.yml Creating /Users/svet/hello1/config/helpers/growler.yml Creating /Users/svet/hello1/config/helpers/lookup.yml Creating /Users/svet/hello1/config/helpers/manager_proxy.yml Creating /Users/svet/hello1/config/helpers/micromenus/collab.rb ...
  23. 23. Hello World en /etc/asterisk/extensions.conf [adhearsion] exten => 101,1,AGI(agi://127.0.0.1) $ cd hello1 en extensions.rb dhearsion { play 'hello-word' } $ ahn start .
  24. 24. internal { case extension when 101...200 employee = User.find_by_extension extension if employee.busy? then voicemail extension else dial employee, :for => 10.rings voicemail unless last_call_successful? end when 888 play weather_report(quot;Dallas Texasquot;) when 999 then +joker_voicemail end }
  25. 25. Adhearsion II: Amazon
  26. 26. require 'amazon/search' r = Amazon::Search::Request.new( '10N1KX1NVQZ2VXXXXXXX') begin resp = r.keyword_search( '0596529260', 'books' ) resp.products.each do |p| unless p.availability =~ /not available/ printf( quot;%s (ASIN %s) -- %snquot;, p.product_name, p.asin, p.our_price ) end end rescue puts quot;No se encuentra.quot; end $ ruby price2 RESTful Web Services (ASIN 0596529260) -- $26.39
  27. 27. Adhearsion II: Amazon adhearsion { require 'amazon/search' r = Amazon::Search::Request.new( '10N1KX1NVQZ2VXXXXXXX') begin resp = r.keyword_search( extension, 'books' ) resp.products.each do |p| unless p.availability =~ /not available/ play p.our_price end end rescue play quot;no-info-about-numberquot; end }
  28. 28. voxbone { sleep 2.seconds play quot;hello-worldquot; isbn = input() require 'amazon/search' r = Amazon::Search::Request.new( '10N1KX1NVQZ2VXXXXXXX') begin resp = r.keyword_search( isbn, 'books' ) resp.products.each do |p| unless p.availability =~ /not available/ play p.our_price end end rescue play quot;no-info-about-numberquot; end }
  29. 29. Telegraph http://telegraph.rubyforge.org • MVC • respond_to
  30. 30. Telegraph y AGI exten => 105, 1, AGI(agi://127.0.0.1/my_route?param1=value) wants.voice do render_voice do |voice| voice.play “hello-world” voice.link_to_dtmf 'bank-lineitem-menu' do link 1, :action=>quot;newquot; link 2, :action=>quot;listquot; link 3, :action=>quot;indexquot; end end end
  31. 31. Demo
  32. 32. <h1>Consultas</h1> <ul> <li> <%= link_to quot;Faltasquot;, :action=>quot;faltasquot; %> </li> <li> <%= link_to quot;Notasquot;, :action=>quot;notasquot; %> </li> </ul> <h1>Consultar notas</h1> <% form_tag '/alumnos/show_notas' do %> DNI: <%= text_field_tag 'dni' %> <%= submit_tag 'Ver notas' %> <% end %> def show_notas @alumno = Alumno.find_by_dni(params[:dni]) @notas = @alumno.notas_ultima_evaluacion end <% @notas.each do |nota| %> <tr> <td class=quot;listquot;><%= nota.asignatura %></td> <td class=quot;listquot;><%= nota.nota %></td> </tr> <% end %>
  33. 33. Telegraph $ script/plugin install svn://rubyforge.org/var/svn/telegraph/trunk en /etc/asterisk/extensions.conf: exten => 777,1, AGI(agi://192.168.1.1:4574/alumnos/index) en app/controllers/alumnos_controller.rb: def index respond_to do |wants| wants.html { render } wants.voice { render_voice { |voice| voice.play_sound quot;hello-worldquot; } } end end
  34. 34. Telegraph: configuración $ vi config/telegraph.yaml development: agi_server: 127.0.0.1 agi_port: 4574 ami_server: druby://localhost:9000 outgoing_call_path: /var/spool/asterisk/outgoing wakeup_call_path: /var/spool/asterisk/wakeups sound_path: /var/lib/asterisk/sounds recording_path: /var/lib/asterisk/sounds $ script/agi_server
  35. 35. respond_to def index respond_to do |wants| wants.html { render } wants.voice { render_voice } end end $ vi app/views/alumnos/index.voice voice.play_sound quot;hello-worldquot;
  36. 36. index # index.rhtml <h1>Consultas</h1> <ul> <li> <%= link_to quot;Faltasquot;, :action=>quot;faltasquot; %> </li> <li> <%= link_to quot;Notasquot;, :action=>quot;notasquot; %> </li> </ul> # index.voice voice.play_sound 'thank-you-for-calling' voice.link_to_dtmf 'presione1-2' do link 1, :controller => quot;alumnosquot;, :action => quot;faltasquot; link 2, :action => quot;notasquot; end
  37. 37. formulario # notas.rhtml <h1>Consultar notas</h1> <% form_tag '/alumnos/show_notas' do %> DNI: <%= text_field_tag 'dni' %> <%= submit_tag 'Ver notas' %> <% end %> # notas.voice voice.form :url=>{:controller => 'alumnos', :action=>'show_notas'} do |form| form.numeric_input 'dni', 'dni', :max_digits=>8 end
  38. 38. resultados # show_notas rhtml <h3>Notas de <%= @alumno.nombre %></h3> <table class=quot;listquot;> <% @notas.each do |nota| %> <tr> <td class=quot;listquot;><%= nota.asignatura %></td> <td class=quot;listquot;><%= nota.nota %></td> </tr> <% end %> </table> # show.voice @notas.each do |nota| voice.play nota.asignatura.to_slug voice.play nota.nota end sleep 2.seconds voice.play quot;vm-goodbyequot;
  39. 39. No hay que pasarse • Web vs Mobile web vs Voz • ej: 466453.com
  40. 40. Telegraph con AMI $ script/generate ami_model AMIModel # environment.rb (user y password en manager.conf): Telegraph::AMIManager.establish_connection!( :host=> 'your.host.name.com', :username=>'user', :secret=>'password') $ script/ami_server # usar así: AMIModel.create(:call, :channel=>'SIP/101', :context=>'default', :exten => 'outgoing', :priority=>1)
  41. 41. Links • http://asterisk.org/ • http://www.voipnovatos.es • http://www.voip-info.org • http://adhearsion.com • http://www.linuxjournal.com/article/9519 • http://telegraph.rubyforge.org • http://telegraph.rubyforge.org/wiki/wiki.pl?UsingAGI
  42. 42. Q &A

×