fala.php
2010-12-31 15:43:53
2010-12-28 17:35:59
Autor: Sony Santos
http://gigawiki.com/sony/fala-php
Permalink: http://gigawiki.com/916
categ = script; linguagem = php; projeto = Reconhecimento de fala; sistema = linux
<?php
# Sistema de reconhecimento de fala. Idioma português brasileiro.
# Mostra um menu de opções e cola o resultado no aplicativo em uso.
# Feito para linux (testado no Ubuntu 10.04). Licença: Domínio público.
# (c) 2010 Sony Fermino dos Santos - http://gigawiki.com/sony/
# Fornecido sem quaisquer garantias. Use por sua conta e risco.
# Veja instruções de uso em http://gigawiki.com/sony/reconhecimento-de-fala
#
# Parte destes comentários foi redigida verbalmente com este programa.

# tempo de espera para executar operações de foco, teclas e clipboard
$sleep = 100000;  # microssegundos

# identifica essa janela
$ultima_ativa = $esta_janela = pega_janela_ativa();

# abre comunicação com o Julius
$f = popen('julius -C opcoes.jconf', 'r');

while (true) {
  # aguarda a saída do julius
  $linha = fread($f, 4096);

  # separa as frases candidatas
  preg_match_all('/sentence...(.*)/m', $linha, $matches);
  $opcoes = $matches[1];

  # ignora a respiração
  $opcoes = array_map('trim', $opcoes);
  if (in_array(utf8_encode('há um ano'), $opcoes)) {
    ignora('respiração', opcoes);
    continue;
  }

  # salva a janela ativa
  $janela_ativa = pega_janela_ativa();

  # loop para certificar-se de que foi escolhida a opção desejada
  while (true) {
    # monta um menu com as opções
    $ret = menu($opcoes);

    if ($ret) {
      # dá opções de pontuação
      $pontos = str_split('.,;:!?');
      array_unshift($pontos, '');

      $ucfirst = mb_strtoupper(mb_substr($ret, 0, 1, 'utf-8'), 'utf-8') .
        mb_substr($ret, 1, 256, 'utf-8');

      $pontuacoes = array();

      foreach(array($ret, $ucfirst) as $frase)
      foreach($pontos as $pt)
      {
        $pontuacoes[] = $frase . $pt;
      }

      $ret = menu($pontuacoes, 2);

      # se foi cancelada, não foi escolhida a opção desejada
      if (!$ret) continue;
    }

    break;
  }

  # restaura o foco
  ativa($janela_ativa);

  if ($ret) {
    # salva o clipboard
    $clip = get_clipboard();

    # copia o resultado para o clipboard
    set_clipboard("$ret ");

    # cola
    tecla("ctrl+v");

    # restaura o clipboard
    set_clipboard($clip);
  }
}

function respira($suspiros = 1) {
  global $sleep;
  for($i = 0; $i < $suspiros; $i++) usleep($sleep);
}

function ativa($wid) {
  global $ultima_ativa;
  if ($wid != $ultima_ativa) {
    shell_exec("xdotool windowactivate $wid");
    $ultima_ativa = $wid;
    respira();
  }
}

function pega_janela_ativa() {
  return shell_exec('xdotool getactivewindow');
}

function tecla($teclas) {
  shell_exec("xdotool key $teclas");
  respira();
}

function set_clipboard($texto) {
  shell_exec("echo -n '$texto' | xsel -i -b");
  respira();
}

function get_clipboard() {
  return shell_exec("xsel -o -b");
}

# monta um menu com as opções (que já devem estar em utf-8)
function menu($opcoes, $etapa = 1) {
  global $esta_janela;

  $etapas = array(1 => 'a frase', 'a pontuação');

  # monta opções de comando
  $op_cmd = '';
  $num_op = 0;
  $tamanho = 0;
  foreach($opcoes as $opcao) {
    if ($opcao) {
      # tira espaços repetidos
      $opcao = preg_replace('/\s{2,}/', ' ', $opcao);
      $op_cmd .= " '$opcao'";
      $num_op++;
      $tamanho += strlen($opcao);
    }
  }

  # na escolha da frase pode haver ruídos
  if ($etapa == 1) {
    # se o tamanho total for pequeno, ignora.
    if ($tamanho < 50) return ignora("tamanho insuficiente: $tamanho", $opcoes);
  }

  # trata textos
  $texto = utf8_encode("Escolha " . $etapas[$etapa]);
  $coluna = utf8_encode('opções');
  $titulo = 'Reconhecimento de fala';

  # calcula a altura
  $height = $num_op * 20 + 180;

  # monta comando
  $comando = "zenity --list --title='$titulo' --text='$texto' --column='$coluna' --height=$height --width=500 $op_cmd";

  # mostra o menu
  ativa($esta_janela);
  $fp = popen($comando, 'r');
  respira(2 + $etapa);

  # seleciona a primeira opção
  tecla('Down');

  # aguarda o resultado
  $ret = fread($fp, 256);
  fclose($fp);

  # estudo para determinar tamanho mínimo a ser considerado
  if (!$ret and $etapa == 1) {
    echo utf8_encode("\nCancelado pelo usuário. Tamanho: $tamanho\n");
  }

  return trim($ret);
}

function ignora($motivo, $opcoes) {
  # loga motivo
  echo "\nIgnorando: " . utf8_encode($motivo . "\nOpções:\n");
  foreach ($opcoes as $opcao) echo "    '$opcao'\n";
  return false;
}

?>
blog comments powered by Disqus
Login:
Senha:
Para logar, você precisa ter o Javascript habilitado.