BLOG ARTICLE 전체 글 | 126 ARTICLE FOUND

  1. 2014.11.04 [Flex] Apache Tour De Flex
  2. 2014.11.04 [Flex] FlexJS™ 를 아십니까?
  3. 2014.10.29 [FlexMobile] Flex Mobile 링크모음
  4. 2014.10.29 [Wowza] 미디어 파일 포멧(컨테이너)의 이해
  5. 2014.10.24 [JavaCore] 파일생성
  6. 2014.10.24 [JavaCore] 텍스트파일 한글 읽어들이기
  7. 2014.10.23 [JavaCore] 시간구하기
  8. 2014.10.22 [Wowza] Wowza Application.xml의 Stream Types 설정
  9. 2014.10.22 [FlexExample] setInterval, clearInterval
  10. 2014.10.22 [FlexExample] Flex 이미지 토글버튼
  11. 2014.10.22 [FlexExample] Flex 이미지 버튼
  12. 2014.10.21 [FFmpeg] 지원 디바이스 보기
  13. 2014.10.20 [node.js] node.js 관련 링크모음
  14. 2014.10.17 [FFmpeg] 동영상 파일에서 이미지 추출
  15. 2014.10.17 [FFmpeg] FFPlay 옵션 도움말 보기
  16. 2014.10.17 [FFmpeg] 미디어 파일 정보 추출
  17. 2014.10.17 [FFmpeg] 지원포멧
  18. 2014.10.17 [FFmpeg] 지원코덱
  19. 2014.10.17 [FFmpeg] 비디오 사이즈 변경하기
  20. 2014.10.17 [FFmpeg] 동영상 파일에 음성만 MP3로 추출
  21. 2014.10.17 [FFmpeg] 동영상 파일에 음성제거
  22. 2014.10.07 [Wowza] Recording Webcam to Wowza Streaming Engine with Flex 3
  23. 2014.09.17 [JavaApplet] JTable 예제
  24. 2014.09.03 [JavaCore] Java 실행 시 Argument 사용과 Option정의
  25. 2014.09.01 [FlexExample] SWF 포커스 잡기
  26. 2014.06.13 [FlexExample] Label의 텍스트 길이 구하기
  27. 2014.04.18 Google Speech API, 그리고 음성인식 기술 14
  28. 2014.03.26 [Flex] BlazeDS환경설정
  29. 2014.01.29 [Wowza] sendResult() 함수와 Responder클래스
  30. 2014.01.28 [Wowza] SharedObject with Flex




 Adobe에서 제공하는 Tour de FLEX가 더 이상 동작하지 않습니다. Apache에서 새로운 버전이 나왔는데, 현재(2014년11월) 301개의 샘플예제가 있고 나름 업데이트도 잘 되는듯 합니다.


 Apache Flex Tour De Flex Component Explorer 1.1



- 왜 Adobe Tour De Flex 는 중단되었는지에 대한 글 :  Tour De Flex is currently not working - desktop or web version. Why?

AND




개발 커뮤니티를 돌아다니던 중 흥미로운 것을 발견하여 기록해 놓습니다. 이름하여 FlexJS!  이름이 모든것을 말해주는 듯 합니다. node.js나 angular.js 등등 수많은 쩜제이에스(.js) 프레임워크들 처럼 "flexjs는 javascript와 flex에 관련된 그 무언가가 아닐까?" 라는 생각이 드는군요.  FlexJS개발자리더 Alex씨가 설명하기를 MXML/AS3 작업물을 Flash나 AIR플랫폼이 아닌 순수 브라우저에서 Flash없이 돌린다는 것입니다. 아래 Workflow를 보시면 ActionScript코드를 JavaScript로 바꿔준다는 걸 알수 있습니다. 




 

2014년 초부터 시작한 프로젝트인듯 하고, 현재(2014년11월) 버전 0.0.2가 나와있습니다.  홈페이지에 보면 a next-generation Flex SDK  이 문구가 가장 가슴에 팍 꽂히네요.   하지만 퍼포먼스가 얼마나 나와주고, 지원속성들을 얼마나 잘 받쳐줄지 걱정부터 앞서네요. ㅠㅠ



- FlexJS 

- PDF : FlexJS: Flex for JavaScript

- Alex Harui의 발표녹화 : FlexJS

AND



- Flex-Mobile-In-Action 예제모음 (괜찮은 예제 많음) : Flex-Mobile-In-Action

- Jason's Flex Blog : Flex Mobile and Flash Builder Tips and Tricks

AND



코덱과 컨테이너의 개념이 잡히지 않아 참고한 글입니다.


-Wowza Article : Understanding streaming protocols and output file formats

AND

import java.io.BufferedWriter;

import java.io.FileWriter;

import java.io.IOException;

 

 

public class TextFileWriter

{

       public static void main(String[] args)

       {

             BufferedWriter bufferedWriter;

             try

             {

                    bufferedWriter = new BufferedWriter(new FileWriter("C:/test.txt"));

                   

                    if(null != bufferedWriter)

                           System.out.println("파일생섬됨");

                    bufferedWriter.write("HelloWorld!");

                    bufferedWriter.close();

             }

             catch (IOException e)

             {

                    e.printStackTrace();

             }

       }

}


AND


import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStreamReader;

 

public class TextFileReader

{

       public static void main(String[] args)

       {

             File file = new File("C:/test.txt");

             InputStreamReader input;

             FileInputStream fis;

             BufferedReader br;

            

             try

             {

                    fis = new FileInputStream(file);

                    input = new InputStreamReader(fis, "UTF-8");

                    br = new BufferedReader(input);

                   

                    int data=0;

 

                    while((data=br.read()) != -1)

                    {

                           System.out.print((char)data);

                    }

                    System.out.println();

                    fis.close();

             }

             catch (FileNotFoundException e)

             {

                    e.printStackTrace();

             }

             catch (IOException e)

             {

                    e.printStackTrace();

             }

 

       }

}


'JAVA > Java Core' 카테고리의 다른 글

[JavaCore] 파일복사 및 이동  (0) 2015.02.02
[JavaCore] 파일생성  (0) 2014.10.24
[JavaCore] 시간구하기  (0) 2014.10.23
[JavaCore] Java 실행 시 Argument 사용과 Option정의  (0) 2014.09.03
AND

import java.text.SimpleDateFormat;

import java.util.Date;

  

public class GetTimeExample {

 

       private static Date date;

      

       static SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");

       static SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

       static SimpleDateFormat format3 = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");

       static SimpleDateFormat format4 = new SimpleDateFormat("yyyy_MM_dd");

       static SimpleDateFormat format5 = new SimpleDateFormat("yyyy_MM_dd_hh_mm");

       static SimpleDateFormat format6 = new SimpleDateFormat("yyyy*MM*dd");

    static SimpleDateFormat format7 = new SimpleDateFormat("yyyyMMdd");

      

       public static void main(String[] args) {

             date = new Date();

            

             trace(format1.format(date));

             trace(format2.format(date));

             trace(format3.format(date));

             trace(format4.format(date));

             trace(format5.format(date));

             trace(format6.format(date));

  trace(format7.format(date));

       }

 

       private static void trace(String msg)

       {

             System.out.println(msg);

       }

            

}



[결과]

AND




Stream Types


Wowza Streaming Engine uses named stream types to control the different types of streaming (live, VOD, chat, remote recording, and so on.). Stream types are automatically configured when you create different application types and configure their options in Wowza Streaming Engine Manager. You can also edit the Streams/StreamType property in Application.xml using a text editor to change the stream type for an application. The following table shows the stream types and their uses.


Stream type

 Description

 default

 VOD

 file

 VOD

 live 

 Publish and play live content (best for one-to-many streaming of live events)

 live-lowlatency

 Publish and play live content (best for one-to-one or one-to-few video/audio chat applications)

 live-record 

 Same as live - in addition content is recorded

 live-record-lowlatency Same as live-lowlatency - in addition content is  recorded
 liverepeater-edge

 Publish and play live content across multiple Wowza servers in an origin/edge configuration (used to configure edge application) 

 liverepeater-edge-lowlatency

 Publish and play live content across multiple Wowza servers in an origin/edge configuration (used to configure edge application when latency is important) 

 liverepeater-edge-origin

 Publish and play live content across multiple Wowza servers in an origin/edge/edge configuration (used to configure a middle-edge application) 

 record

 Video recoring 

 rtp-live

 Re-stream RTSP/RTP, native RTP, or MPEG-TS streams 

 rtp-live-lowlatency

 Re-stream RTSP/RTP, native RTP, or MPEG-TS streams when latency is important 

 rtp-live-record

 Same as rtp-live - in addition content is recorded 

 rtp-live-record-lowlatency

 Same as rtp-live-lowlatency - in addition content is recorded 
 shuotcast

 Re-stream SHOUTcast/Icecast MP3 or AAC+ audio streams 

 shoutcast-record

 Same as shoutcast - in addition content is recorded 


Each stream type exposes properties that are used for tuning the stream type. For example, the stream type definitionsfor live and live-lowlatency differ only in the tuning that's accomplished through the stream properties. Defined properties for a stream type can be overridden on a per-application basis by defining new property values on an application's Propertiestab in the Streaming Engine manager or by editing the Streams/Properties container in Application.xml.


[출처] WowzaStreamingEngine UserGuide.pdf

AND


<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

                       xmlns:s="library://ns.adobe.com/flex/spark"

                       xmlns:mx="library://ns.adobe.com/flex/mx"

                       minWidth="955"

                       minHeight="600">

 

       <fx:Script>

             <![CDATA[

                    import flash.utils.clearInterval;

                    import flash.utils.setInterval;

                   

                    import mx.controls.Alert;

                   

                   

                    protected function onClick(event:MouseEvent):void

                    {

                           var myInterval:uint = setInterval(test, 2000);

                          

                           function test():void

                           {

                                 Alert.show("Alert실행");

//                               clearInterval(myInterval);

                           }

                    }

                   

             ]]>

       </fx:Script>

       <s:Button label="2초후 Alert창 띄움" click="onClick(event)"/>

</s:Application>


AND



ImageToggleButtonExample.fxp


- 더 이쁜 이미지 아이콘 : Advanced FXG Spark Icon Buttons


AND



ImageButtonExample.fxp



[출처] Create Your Own Image Buttons In Flex4

AND


1. 명령어

ffmpeg -list_devices true -f dshow -i dummy




2. 결과




[출처] FFmpeg Documentation

'Media > FFmpeg' 카테고리의 다른 글

[FFmpeg] 동영상 파일에서 이미지 추출  (0) 2014.10.17
[FFmpeg] FFPlay 옵션 도움말 보기  (0) 2014.10.17
[FFmpeg] 미디어 파일 정보 추출  (0) 2014.10.17
[FFmpeg] 지원포멧  (0) 2014.10.17
[FFmpeg] 지원코덱  (0) 2014.10.17
AND


- 조대협님의 글 : node.js의 장단점에 대해서

- Realtime Web Stats Using Node.js, Socket.IO and Redis

Horizontally Scaling Node.js and WebSockets with Redis

Socket.io-Redis Real Time Chat Example

A Node.js chat app using Express 3.x, Redis Pub/Sub + Redis SessionStore + Socket.io + Socket.Sessions that shows scaling on Cloud foundry

- Node.js 메모리 관리

- 동영상 강좌 : 빠르게 훝어보는 node.js 온라인 강좌

- 무료호스팅 : heroku

- 네이버 hello world : Node.js로 CUBRID를

- node.js의 성능은 과연 얼마나 될까??

- 한국커뮤니티(매우유익함!) : play.node();

- Node.js 기본 사용법

- Simple Chat application using node.js and socket.io

AND


1. 명령어

ffmpeg -i 1080.mp4 -an -r 1 -y -s 320x240 output%d.jpg


-an : 오디오 무시

-r 1 : 매 1초마다 

-y : 같은파일 이름이 있을 시 덮어쓰기

-s : 결과이미지 크기 지정



2. 결과







'Media > FFmpeg' 카테고리의 다른 글

[FFmpeg] 지원 디바이스 보기  (0) 2014.10.21
[FFmpeg] FFPlay 옵션 도움말 보기  (0) 2014.10.17
[FFmpeg] 미디어 파일 정보 추출  (0) 2014.10.17
[FFmpeg] 지원포멧  (0) 2014.10.17
[FFmpeg] 지원코덱  (0) 2014.10.17
AND


1. 명령어

ffplay -h



2. 결과



'Media > FFmpeg' 카테고리의 다른 글

[FFmpeg] 지원 디바이스 보기  (0) 2014.10.21
[FFmpeg] 동영상 파일에서 이미지 추출  (0) 2014.10.17
[FFmpeg] 미디어 파일 정보 추출  (0) 2014.10.17
[FFmpeg] 지원포멧  (0) 2014.10.17
[FFmpeg] 지원코덱  (0) 2014.10.17
AND

1. 명령어

ffmpeg -i 1080.mp4



2. 결과



'Media > FFmpeg' 카테고리의 다른 글

[FFmpeg] 동영상 파일에서 이미지 추출  (0) 2014.10.17
[FFmpeg] FFPlay 옵션 도움말 보기  (0) 2014.10.17
[FFmpeg] 지원포멧  (0) 2014.10.17
[FFmpeg] 지원코덱  (0) 2014.10.17
[FFmpeg] 비디오 사이즈 변경하기  (0) 2014.10.17
AND

[FFmpeg] 지원포멧

Media/FFmpeg 2014. 10. 17. 11:29


1. 명령어

ffmpeg -formats



2. 결과



AND

[FFmpeg] 지원코덱

Media/FFmpeg 2014. 10. 17. 11:25


1. 명령어

ffmpeg -codecs



2. 결과




AND


1. 명령어

ffmpeg -i 1080.mp4 -s 320x240 10802.mp4



2. 속성비교                         


                                     



3. 용량비교

'Media > FFmpeg' 카테고리의 다른 글

[FFmpeg] 미디어 파일 정보 추출  (0) 2014.10.17
[FFmpeg] 지원포멧  (0) 2014.10.17
[FFmpeg] 지원코덱  (0) 2014.10.17
[FFmpeg] 동영상 파일에 음성만 MP3로 추출  (0) 2014.10.17
[FFmpeg] 동영상 파일에 음성제거  (0) 2014.10.17
AND


1. 명령어

ffmpeg -i 1080.mp4 -vn 10803.mp3



2. 속성비교

                              

                                 





















3. 용량비교





'Media > FFmpeg' 카테고리의 다른 글

[FFmpeg] 미디어 파일 정보 추출  (0) 2014.10.17
[FFmpeg] 지원포멧  (0) 2014.10.17
[FFmpeg] 지원코덱  (0) 2014.10.17
[FFmpeg] 비디오 사이즈 변경하기  (0) 2014.10.17
[FFmpeg] 동영상 파일에 음성제거  (0) 2014.10.17
AND


1. 명령어

ffmpeg -i 1080.mp4 -an 10802.mp4



2. 속성비교


                                  




3. 용량비교



'Media > FFmpeg' 카테고리의 다른 글

[FFmpeg] 미디어 파일 정보 추출  (0) 2014.10.17
[FFmpeg] 지원포멧  (0) 2014.10.17
[FFmpeg] 지원코덱  (0) 2014.10.17
[FFmpeg] 비디오 사이즈 변경하기  (0) 2014.10.17
[FFmpeg] 동영상 파일에 음성만 MP3로 추출  (0) 2014.10.17
AND


This is the simplest webcam recording application to Wowza with Flex. Almost source code is from the example based on Flash provided by Wowza.([install-dir]/examples/WebcamRecording/FlashRTMPPlayer11 


Don't forget to configure the Application.xml and to make Application directory first. And recorded files should be located in the [install-dir]/content folder unless you have changed the Application.xml /Streams .  


Feel free to edit and modify the source code. :)



WowzaRecorder.fxp




wowza stream recorders

Recording Decent Quality Video and Audio With Flash and Red5

Wowza Tutorial - How to set up live streaming using an RTMP-based encoder

Wowza Tutorial - How to convert Flash Player 11 output from H.264 + Speex audio to H.264 + AAC audio using Wowza Transcoder AddOn

Wowza Tutorial - How to move recordings from live streams (ModuleMediaWriterFileMover)

Wowza Tutorial - How to set up live video recording

Wowza Tutorial - How to record live streams (Wowza Streaming Engine)

Wowza Tutorial - How to start and stop live stream recordings programmatically (LiveStreamRecordAutoRecord example)

Wowza Tutorial - How to record live streams (HTTPLiveStreamRecord)

AND



import java.awt.*;

import javax.swing.*;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

 

public class UseJTable extends JFrame {

 

        private static final long serialVersionUID = 1L;

 

        public UseJTable() {

               super("JTable");

               setSize(300, 200);

               addWindowListener(new WindowAdapter(){

                       public void windowClosing(WindowEvent windowevent)

                       {

                              Window window = windowevent.getWindow();

                              window.dispose();

                              System.exit(0);

                       }

               });

               JTable jtable = new JTable(new String[][] {

                              {"Tom", "24"}, {"Kevin", "25"},

                              {"Dave", "24"},{"Michael", "24"},

                              {"Jimmy", "24"},{"Remy", "24"},

                              {"Alice", "24"},{"Jo", "24"}},

                              new String[] {"Name", "Age"});

               jtable.setRowHeight(25);

               jtable.setGridColor(Color.BLUE);

               JScrollPane jScrollPane = new JScrollPane(jtable);

               getContentPane().add(jScrollPane, BorderLayout.CENTER);

        }

 

        public static void main(String args[]) {

               UseJTable st = new UseJTable();

               st.setVisible(true);

        }

} 

[출처] javadocexamples.com


AND


Java 어플리케이션 실행 시, Argument 사용법과, 더 나아가 옵션을 정의하고 받아온 옵션을 출력하는 간단한 예제입니다. .jar파일로 묶여있는 Applet 실행 시에도 사용가능하며, .exe로 컴파일된 실행파일에서도 사용이 가능합니다.



1. Java Argument


Java Application은  main메소드의 인자값으로 String타입의 배열형태로 받도록 되어있습니다.  아래 예제는 Java실행 시, argument를 출력해주는 예제입니다.



 public class ArgumentExample {

 

        public static void main(String[] args) {

 

               if(args!=null)

               {

                       for(int i=0; i<args.length; i++)

                       {

                              System.out.println("args["+i+"]="+args[i]);

                       }

               }

        }

}



| 이클립스에서 실행시



| 결과화면



| Console에서 실행 시





2. Java실행 시 옵션 만들기


Java Application 실행 시 옵션을 넣는 예제입니다. GNU라이센스를 따르며, Googling을 통해 얻은 소스를 바탕으로, 샘플링 한 예제입니다.


import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

 

import jargs.gnu.CmdLineParser;

import jargs.gnu.CmdLineParser.Option;

 

 

public class CmdLineParserExample {

 

               private List<String> optionHelpStrings = new ArrayList<String>();

       

               public static void main(String[] args) {

                       CmdLineParserExample main = new CmdLineParserExample();

                       CmdLineParser parser = new CmdLineParser();

                      

                       // Define Option Help

                       CmdLineParser.Option host = main.addHelp(parser.addStringOption('o', "output"), "This is option test.");

       

                       try {

                              parser.parse(args);

                             

                              System.out.println(parser.getOptionValue(host));

                             

                       } catch (CmdLineParser.OptionException e) {

                              System.err.println(e.getMessage());

                              main.printUsage();

                              System.exit(2);

                       }

               }

       

               private Option addHelp(Option option, String helpString) {

                       optionHelpStrings.add(" -" + option.shortForm() + ", --" + option.longForm() + ": " + helpString);

                       return option;

               }

              

               private void printUsage() {

                System.err.println("usage: CmdLineParser Example [options]");

                for (Iterator<String> i = optionHelpStrings.iterator(); i.hasNext(); ) {

                       System.err.println(i.next());

                }

            } 

}

[소스코드]  CmdLineParser.zip

[Reference] CmdLineParser Reference

[출처] Googling


| 이클립스에서 실행시



| 결과화면



| Console에서 실행 시



* 참고 : How to parse command line arguments in Java

'JAVA > Java Core' 카테고리의 다른 글

[JavaCore] 파일복사 및 이동  (0) 2015.02.02
[JavaCore] 파일생성  (0) 2014.10.24
[JavaCore] 텍스트파일 한글 읽어들이기  (0) 2014.10.24
[JavaCore] 시간구하기  (0) 2014.10.23
AND

  /*

   * 실행시 포커스 잡기

   */

  if(ExternalInterface.available)

  {

        ExternalInterface.call("eval", "document.getElementById('" + ExternalInterface.objectID + "').tabIndex=0");

        ExternalInterface.call("eval", "document.getElementById('" + ExternalInterface.objectID + "').focus()");

  }


  /*

   * 컴포넌트 포커스 잡기

   */

  userNameTextInput.setFocus();

  


* Managing Initial SWF Focus in All browsers

AND


Label의 추가되는 글자의 길이가 Label컴포넌트의 길이를 벗어나려하면 지우고 다시 쓰는 예제입니다. Label컴포넌트의 measureText속성이 KeyPoint입니다.



<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

                       xmlns:s="library://ns.adobe.com/flex/spark"

                       xmlns:mx="library://ns.adobe.com/flex/mx">

 

       <fx:Script>

             <![CDATA[

                    import flash.utils.setTimeout;

 

                    import mx.events.FlexEvent;

 

                    private var i:Number=0;

                    private var testTimer:Timer;

 

                    private function onClick():void

                    {

                           testTimer=new Timer(100, 1000);

                           testTimer.addEventListener(TimerEvent.TIMER, timerHandler);

                           testTimer.start();

                    }

 

                    public function timerHandler(event:TimerEvent):void

                    {

                           if (lbl.measureText(lbl.text).width > lbl.width - 20)

                                 lbl.text="";

 

                           lbl.text+=i.toString();

                           i++;

                    }

             ]]>

       </fx:Script>

 

       <s:VGroup>

             <mx:Button click="onClick()"/>

             <s:Label id="lbl"

                            backgroundColor="#FF0000"

                            width="100"/>

       </s:VGroup>

</s:Application>


measureText Reference

AND



패턴인식(Pattern Recognition)의 한 분야인 음성인식은 오늘날(현 2014년) 많이 대중화가 되어있고, 다양한 분야에서 활용되고 있습니다.  음성인식에서 두각을 나타내고있는 여러 대기업들중 Google에서 제공하는 STT(Speech To Text)의 활용법에 대해 간단히 정리한 내용입니다.  글쓴이는 음성인식 분야에 무지하며, 이를 참조해서 읽어주세요.


인식률은 사람의 성별, 사용된 마이크, 주변 잡음, 인식할 단어의 수, 얼마나 문법적으로 올바른 문장을 발화하는가 등 다양한 요소에 의해서 좌우됩니다. 따라서 인식 성능이 얼마나 나올 것인가를 결정하려면 이러한 조건들이 명확하게 알아야하고, 그 후에야 대강의 성능을 예측하여 볼 수 있습니다.

[출처] 음성인터페이스연구실 게시판 발췌하였습니다.



1. Google의 음성인식


① x-webkit-speech (HTML5 Speech Input API)


2011년 Google이 자사 브라우저 Chrome 버전11.0.696.16 Beta 버전부터 HTML5 Speech Input API Specification를 지원하였습니다. 이는 다른 미들웨어(Flash, ActiveX)의 도움없이 브라우저에서 마이크로부터의 input을 캡쳐해 낼수 있게됩니다.  x-webkit-speech라는 이름으로 input태그에 아래와같이 x-webkit-speech속성만 추가하시면, 음성인식 샘플테스트를 해보실 수 있습니다. 아래 마이크를 클릭하시고 말해보세요~(크롬에서만 동작)

 

 <input x-webkit-speech="" id="mike" style="width:500px;height:100px"> 


 <- 마이크 클릭


테그의 속성하나만을 추가해도 음성인식이 되는 매력적인 기능이지만 슬프게도 2014년 4월 현재, 다른 브라우저의 지원이 부족하고, 태그의 속성으로만 사용할 수 있기에 확정성이 용이하지 못하였습니다. 이러한 이유로 x-webkit-speech의 사용은 점점 사라져 가는 추세입니다. 대신 자바스크립트API인 Web Speech API가 등장하게 됩니다.



② New Approach : Web Speech API


2013년 Chrome 버전25 부터 Web Speech API Specification를 지원하게 됩니다. 음성을 텍스트포멧으로 변환(Speech To Text, 이하 STT)이 순수 웹브라우저만으로 가능해 졌습니다.


 (데모소스코드)   



 Speech Input API 스펙은 HTML5스펙이었다면, Web Speech API는, HTML5스펙에 포함된 것이 아니라 따로 독립적인 Speech API가 독립적으로 분리되어 있습니다.  Web Speech API 소개를 간추리면 아래와 같습니다.


*출처:Web Speech API Creates Interactive Experiences




③ 크롬브라우저 확장기능인 Google Voice Search Hotword


이 기술을 이용해 Google은 'Hands free'라는 모토로 확장기능을 제공하고 있습니다. 이는 Apple의 Siri와 같은 개념으로, 말로써 검색을 하고, 이메일을 보내는 등 좀 더 편리한 PC웹브라우징을 하실 수 있습니다.


Google Voice Search Hotword(beta)로 가셔서 설치하시고, 설정->확장 프로그램-> Google Voice Search Hotword(Beta) 0.1.1.5 사용 설정을 합니다.



 google.co.kr 이 아닌 google.com으로 접속하시면 다음과 같이 'OK Google'이라고 말하세요. 라는 문구를 검색어 창에서 확인하실 수 있습니다. Apple의 Siri와 같이, Chrome브라우저에서 음성명령만으로 검색이 가능해졌습니다. 단, 아직 베타버전이어서 한국어 지원을 하지 않습니다.




2. 어떻게 동작하는가


Google Speech API는 크게 두가지 형태로 디자인 되었습니다.


첫째, 크롬브라우저에 음성엔진이 built-in

둘째, 구글서버로 음성Data를 보내고 feedback받는 형태


두개지 방법에는 장단점이 있습니다. 크롬브라우저 자체 내에 음성인식엔진이 내장되어 있는경우 서버를 거치지 않기때문에 속도가 빠름니다.  서버를 거치게 될 경우, 내장엔진에 저장되어있는 data보다 훨씬 방대한 data가 저장되어 있기때문에, 내장음성엔진에 비해 정확도가 더 높다고합니다.



3. Google Speech API Server 이용해보기

※ Google Speech API 의 사용은 개발목적과 개인사용에 한합니다.  


 ① Chromium-dev 가입 

Chromium-dev Community로 가셔서 회원가입을 합니다. 가입하지 않으면 API설정에 Speech API 자체가 보이지 않습니다.


 ② Speech API 사용설정

Chromium-dev에 가입하셨다면 Google Developers Console로 가보면 Speech API가 보일것입니다.  STATUS를 ON으로 바꿔주세요. 하루 50번의 요청제한이 있습니다. 단, 요청횟수를 더 늘릴 수도 있습니다.



③ key만들기




④ Google서버로 요청


Google Speech API를 이용하시려면, HTTP POST 요청을 합니다. Google Speech API v2버전에서는 다음의 두가지 data형식을 인식할 수 있습니다. 클라이언트가 어떤 언어로 되어있든, Google서버에 요청시 아래의 형태를 맞추셔야합니다. 


Data 인코딩 정보

1. FLAC

Flac file; 44100Hz 32bit float, exported with Audacity. Check the audio folder in this repository for some hilarious examples.

Channels       : 2

Sample Rate    : 44100

Precision      : 32-bit

Sample Encoding: 32-bit Float


2. 16-bit PCM

The following audio options are confirmed working for 16-bit PCM sample encoding:

Channels       : 1

Sample Rate    : 16000

Precision      : 16-bit

Sample Encoding: 16-bit Signed Integer PCM


요청 Header정보

1. Flac

Content-Type: audio/x-flac; rate=44100;

FLAC파일의 rate와 똑같이 맞춰주셔야 합니다. 일반적으로 44100Hz로 맞추지만, 다른 rate도 지원을 합니다.


2. 16-bit PCM

Content-Type: audio/l16; rate=16000;

16bit signed-integer로 인코딩된 파일은 44100Hz 혹은 16000Hz를 지원합니다. 


※주의 : 오디오 캡처할때 rate와 header의 rate는 같아야 합니다!


HOST 주소

https://www.google.com/speech-api/v2/recognize


KEY값
AIzaSyCnl6MRydhw_5fLXIdASxkLJzcJh5iX0M4

위의 키값은 위에서 언급한 Google Hotword Chrome Extension에서 쓰이는 키값으로, 소스코드에서 추출한 키값입니다.  Google Developers Console에서 생성된 키값을 입력하여도 되고,  Google Hotword Chrome Extension에서 추출한 키값을 입력하셔도 됩니다. 다만, 생성한 키값은 하루 50회 이용제한이 있고, Google Hotword Chrome Extension에서 추출한 키값은 이용제한이 없습니다.

2014년 5월. 위의 키값은 더이상 동작하지 않습니다. Google에서 막아놓은듯 합니다. 그리고 v1버전도 어쩌다 동작할 때도 있는듯 하고, 직접 추출된 50회 이용제한 Key값또한 50회 이상 되고 있군요.  하루중 몇번씩 되었다 안되었다 하는.... ㅠㅠ


LANG값

var langs =

[['Afrikaans',       ['af-ZA']],

 ['Bahasa Indonesia',['id-ID']],

 ['Bahasa Melayu',   ['ms-MY']],

 ['Català',            ['ca-ES']],

 ['Čeština',          ['cs-CZ']],

 ['Deutsch',         ['de-DE']],

 ['English',          ['en-AU', 'Australia'],

                     ['en-CA', 'Canada'],

                     ['en-IN', 'India'],

                     ['en-NZ', 'New Zealand'],

                     ['en-ZA', 'South Africa'],

                     ['en-GB', 'United Kingdom'],

                     ['en-US', 'United States']],

 ['Español',          ['es-AR', 'Argentina'],

                     ['es-BO', 'Bolivia'],

                     ['es-CL', 'Chile'],

                     ['es-CO', 'Colombia'],

                     ['es-CR', 'Costa Rica'],

                     ['es-EC', 'Ecuador'],

                     ['es-SV', 'El Salvador'],

                     ['es-ES', 'España'],

                     ['es-US', 'Estados Unidos'],

                     ['es-GT', 'Guatemala'],

                     ['es-HN', 'Honduras'],

                     ['es-MX', 'México'],

                     ['es-NI', 'Nicaragua'],

                     ['es-PA', 'Panamá'],

                     ['es-PY', 'Paraguay'],

                     ['es-PE', 'Perú'],

                     ['es-PR', 'Puerto Rico'],

                     ['es-DO', 'República Dominicana'],

                     ['es-UY', 'Uruguay'],

                     ['es-VE', 'Venezuela']],

 ['Euskara',         ['eu-ES']],

 ['Français',        ['fr-FR']],

 ['Galego',          ['gl-ES']],

 ['Hrvatski',        ['hr_HR']],

 ['IsiZulu',         ['zu-ZA']],

 ['Íslenska',        ['is-IS']],

 ['Italiano',        ['it-IT', 'Italia'],

                     ['it-CH', 'Svizzera']],

 ['Magyar',          ['hu-HU']],

 ['Nederlands',      ['nl-NL']],

 ['Norsk bokmål',    ['nb-NO']],

 ['Polski',          ['pl-PL']],

 ['Português',       ['pt-BR', 'Brasil'],

                     ['pt-PT', 'Portugal']],

 ['Română',          ['ro-RO']],

 ['Slovenčina',      ['sk-SK']],

 ['Suomi',           ['fi-FI']],

 ['Svenska',         ['sv-SE']],

 ['Türkçe',          ['tr-TR']],

 ['български',       ['bg-BG']],

 ['Pусский',         ['ru-RU']],

 ['Српски',          ['sr-RS']],

 ['한국어',            ['ko-KR']],

 ['中文',             ['cmn-Hans-CN', '普通话 (中国大陆)'],

                        ['cmn-Hans-HK', '普通话 (香港)'],

                        ['cmn-Hant-TW', '中文 (台灣)'],

                        ['yue-Hant-HK', '粵語 (香港)']],

 ['日本語',           ['ja-JP']],

 ['Lingua latīna',   ['la']]];


Request 예제 (Flex로 만든 예제, Google서버로 요청하는 부분입니다.)

 .

 .

 .                         

 var PATH:String = "https://www.google.com/speech-api/v2/recognize?output=json&lang=ko-kr&key=AIzaSyCnl6MRydhw_5fLXIdASxkLJzcJh5iX0M4";

 var urlRequest:URLRequest = new URLRequest(PATH);

 var urlLoader:URLLoader = new URLLoader();

 urlRequest.contentType = "audio/x-flac; rate=44100";

//urlRequest.contentType = "audio/l16; rate=16000";

 urlRequest.data = flacData;

 urlRequest.method = URLRequestMethod.POST;

 urlLoader.dataFormat = URLLoaderDataFormat.TEXT;

 urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);

 urlLoader.addEventListener(ErrorEvent.ERROR, urlLoader_error);

 urlLoader.load(urlRequest);

 .

 .

 .



JSON으로 리턴되며, XML은 지원하지 않습니다.

 {

"result":[

{

"alternative":[

  {"transcript":"안녕하세요","confidence":0.57016742}

 ,{"transcript":"아냐세요"}

 ,{"transcript":"안냐세요"}

                                          ]

  ,"final":true

                }

 ]

,"result_index":0

 }


4. Google Speech API Server를 통해 서비스가 가능한가


Google Speech API는 무료이지만 공식적인 API(Official Public API)는 아닙니다.  말인즉 공식적인 API가 아니므로, Google은 사전예고없이 API를 바꿔버리면 예상치 못한 여러 에로사항이 생길 가능성이 다분합니다. 한가지 예로 2012년 Google의 일방적(?)인 Google Weather API차단으로 이를 이용해 날씨서비스를 하던 많은 기업들이, 다른 Weather API로 갈아탓더랬습니다. (stackoverflow) 또한 위에서 업급했던 것처럼, 개발과 개인에게만 사용을 허가합니다. 



5. 흥미로운 음성 엔진들


① Sphinx (100% Open Source Toolkit For Speech Recognition)


CMUPhinx는 미국 펜실베이니아에 위치한 카네기멜론대학(Carnegie Mellon University)의 Sphinx그룹과 Sun Microsystems연구소, Mitsubishi Electric Research Labs (MERL), and Hewlett Packard (HP)들이 협력해서 연구개발중인 음성엔진입니다.  (소스코드Tutorial





② MIT의 WAMI

WAMI는 MIT 연구실에서 만든 iPhone, iPod Touch 모바일 웹브라우저에서 음성인식을 하는 toolkit입니다. 이것도 역시 오픈소스입니다.


③ Online Speech Recognition API





6. Flex로 구현해본 음성인식 샘플


크로스 브라우징 Google STT 구현을 위해, 마이크Input을 Flex로 받아와서 처리를 해보았습니다.  




7. 끝으로...(Graphic User Interface -> Voice User Interface)


후드래빗님의 의견처럼 '음성인식 기술이 새로운 인터페이스로 자리잡고 있다' 에 100% 동의합니다. 아니면 '이미 자리잡았다' 가 될 수도 있겠네요. Warable Device, 자동차, 의료, 스마트TV, 게임, 교육 등등 다양한 분야에 활용되고 있습니다. MS의 코타나, 구글의 Now, 애플의 Siri 등 공룡기업들의 '개인비서' 서비스가 강세를 보이는 가운데, 우리나라에서도 음성인식 기술에 대한 연구가 활발하게 진행중입니다. 대표적으로 2010년 네이버는 음성검색엔진을 자체 기술로 개발하기시작한 이래로, 현재는 Google음성엔진에 못지않은 음성인식률을 보이고 있습니다. '다음'은 음성 검색 서비스 강화를 위해 음성인식 전문기업 '다이알로이드'를 인수하고, 최근(2014년2월)에 '다음'은 국내최초로 국내최초로 '모바일 음성 인식 API' 를 공개하기도 하였습니다. 


인공지능과 Voice User Interface의 끝을 보여주는 영화 'her'  


끝으로 우리나라가 IT강국이라 하지만, 순수 '대한민국 소프트웨어 기술'이라 내세울 만한 것 하나 없는 이 현실에서, 소수의 우리나라 음성인식 기술자분들의 노고에 감사를 드립니다~



* 참고 (이 글은 아래의 사이트를 참고로 작성하였습니다.)


* W3C 음성인식 커뮤니티 : W3C Speech API Community Group

* W3C 오디오 API : Web Audio API

* W3C Speech Input : HTML5 Speech Input API Specification

* W3C Speech : Web Speech API Specification

* Web Speech Presentation문서 : Web Speech API Creates Interactive Experiences

* Web Speech API 사용법 : Example on how to user Web Speech API

* Google Speech API v1(Github) - Google Speech To Text API

Google Speech API v2(Github) - Reverse Engineering Google's Speech To Text API (v2)

* Chomium Speech 소스코드 - http://src.chromium.org/viewvc/chrome/trunk/src/content/browser/speech/

* 도움글 : Accessing Google Speech API / Chrome 11

* 도움글 : Google’s Speech API (옵션설명)

* 도움글 : stackoverflow질문답변

* nodejs for Google Speech API : Google Speech API wrapper for node

* 관련유틸 : SoX (콘솔 사운드파일 포멧변경유틸)

* 관련기사 : 이젠 노트북과 PC에서도 "OK, 구글" … 구글, 음성 검색 확장 기능 공개

* 관련기사 : 넥서스5의 핵심 기능 'Ok Google', 한국어로는 사용 불가

* 관련글 : 음성검색, '열려라 참깨'의 비밀

* 관련글 : KLDP 게시판 글 (음성인식 공부방법, 책, 참고사이트)

* 음성인식 강의 : 충북대학교 권오욱 교수의 음성인식 한글강의

* 충북대학교 : 음성통신연구실 SC Lab

* 카이스트 음성인식연구실 : 한국과학기술원 전기전산학과 음성 인터페이스 연구실

* 음성관련 논문자료 : 사단법인 한국 음성 학회

* 음성/언어정보연구센터 :  ETRI

* HTK 공식 홈페이지 :  http://htk.eng.cam.ac.uk/

* AS3-STT : SimpleSoundApp

* Flash on flac encoder : Flach Encoder

* Flash-Red5-Spring-Sphinx : Java Speech Recognition and Adobe Flex

* Java이용, Google STT 예제 : SPEECH TO TEXT LIBRARY FOR PROCESSING

* Java 음성API 개발 문서 : Java Speech API Programmer's Guide

* Sphinx관련 URL 모음 : Open Source Speech Software from Carnegie Mellon University

* Sphinx Java 예제 만들기 : How to Make Simple Speech to Text Recognition using Java Sphinx

* 음성인식오픈소스 링크모음 : Open source Speech Projects

* Flash기반 음성인식 예제 : Voice Gesture

* Java기반 음성인식 (TalkingJava SDK 이용, NON-COMMERCIAL 라이센스) : Speech To Text using Java API

* Java 사운드 : Java Sound, An Introduction

'HTML > HTML News' 카테고리의 다른 글

[HTML5] HTML5 링크모음  (0) 2014.11.10
AND

BlazeDS 환경설정하는 방법을 처음부터 녹화해둔 영상입니다.  지돌스타님의 글을 참조하여 셋팅하였습니다.



AND





sendResult는 Flex의 Responder 클래스와 짝을 이룹니다.  NetConnection클래스의 call()함수로 서버측 메소드를 호출 할 경우, 서버측에서 클라이언트로 결과를 반환 해야 하는 경우 유용합니다.  클라이언트쪽에서는 Responder클래스를 이용해 응답을 받습니다.


1. sendResult 기본 예제


* Server측 소스

 ...

 public void sendResultTest(IClient client, RequestFunction function, AMFDataList params) {

      sendResult(client, params, "Hello World!");

 }

 ...

   

* Client측 소스

 ...

 nc.call("sendResultTest", new Responder(function(data:Object):void

 {

       Cc.log(data);

 }));

 ...

                 


Tutorial6.fxp

Tutorial6.java

 



2. sendResult 활용 예제


아래 소스는 WOWZA에서 제공해주는 예제입니다. 아~주 유용하고, 여러가지로 활용될 예제라 눈여겨 봐야할 것 같습니다~ 서버측 접속정보(총원, 스트림정보 등)를 알아내는 예제입니다.


[출처] How to get connection counts for server, applications, application instances sent to a Flash application


* Server측 소스

 ...

 public void getServerConnectionCount(IClient client, RequestFunction function, AMFDataList params)

 {

      Server server = Server.getInstance();

      int count = (int)server.getConnectionCounter().getCurrent();

      sendResult(client, params, count);

 }

 

  public void getApplicationConnectionCount(IClient client, RequestFunction function, AMFDataList params)

  {

      IApplication application = client.getApplication();

      int count = (int)application.getConnectionCounter().getCurrent();

      sendResult(client, params, count);

  }

 

  public void getApplicationInstanceConnectionCount(IClient client, RequestFunction function, AMFDataList params)

  {

      IApplicationInstance applicationInstance = client.getAppInstance();

      int count = (int)applicationInstance.getConnectionCounter().getCurrent();

      sendResult(client, params, count);

  }

 

  public void getStreamConnectionCount(IClient client, RequestFunction function, AMFDataList params)

  {

      String streamName = params.getString(PARAM1);

      int count = 0;

      IApplicationInstance applicationInstance = client.getAppInstance();

      List<IMediaStream> streamList = applicationInstance.getPlayStreamsByName(streamName);

      if (streamList != null)

      count = streamList.size();

      sendResult(client, params, count);

  }

 

  public void getStreamClientIds(IClient client, RequestFunction function, AMFDataList params)

  {

      AMFDataArray clientList = new AMFDataArray();

      String streamName = params.getString(PARAM1);

      IApplicationInstance applicationInstance = client.getAppInstance();

      List<IMediaStream> streamList = applicationInstance.getPlayStreamsByName(streamName);

      if (streamList != null)

      {

         Iterator<IMediaStream> iter = streamList.iterator();

         while (iter.hasNext())

         {

             IMediaStream stream = iter.next();

             if (stream == null)

                  continue;

             IClient sclient = stream.getClient();

             if (sclient == null)

                  continue;

             clientList.add(new AMFDataItem(sclient.getClientId()));

         }

      }

      sendResult(client, params, clientList);

 }

 ...

   

* Client측 소스

 ...

 Cc.clear();

 var ncServerResults:Object = new Object()

 ncServerResults.onResult = function(count:Number):void

 {

        Cc.log("server: "+count);

 }

 nc.call("getServerConnectionCount", new Responder(ncServerResults.onResult));

                            

 var ncApplicationResults:Object = new Object()

 ncApplicationResults.onResult = function(count:Number):void

 {  

Cc.log("application: "+count);

 }

 nc.call("getApplicationConnectionCount", new Responder(ncApplicationResults.onResult));

                            

 var ncAppInstanceResults:Object = new Object()

 ncAppInstanceResults.onResult = function(count:Number):void

 {

       Cc.log("appInstance: "+count);

 }

 nc.call("getApplicationInstanceConnectionCount", new Responder(ncAppInstanceResults.onResult));

                          

 var streamName:String = "myStream";

                          

 var ncStreamResults:Object = new Object()

 ncStreamResults.onResult = function(count:Number):void

 {

       Cc.log("stream: "+count);

 }

 nc.call("getStreamConnectionCount", new Responder(ncStreamResults.onResult), streamName);

                          

 var ncStreamListResults:Object = new Object()

 ncStreamListResults.onResult = function(list:Array):void

 {

       Cc.log("clients");

       for(var i:Number=0;i<list.length;i++)

              Cc.log("["+i+"]: "+list[i]);

 }

 nc.call("getStreamClientIds", new Responder(ncStreamListResults.onResult), streamName);

 ...

   

Tutorial7.fxp

Tutorial7.java


AND




SharedObject(이하 SO)는 크게 두가지로 구분하여 사용할 수 있습니다.


첫째, 로컬에서만 사용할 경우. 여러가지 상황에서 쓰일 수 있겠으나, 저같은 경우는 Flex로 모바일 앱 개발할 때 세션을 유지하는 방법으로 사용하였습니다.

[참고] Flex모바일 개발시 Session유지  


두번째, 미디어 서버를 통해 SO에 연결(connect)된 모든 Client들에게 Data를 공유하는 방법입니다.


1. SharedObject에 연결된 다른 클라이언트의 함수 호출해 보기 


   SharedObject.send()함수를 통해 SO에 연결된 모든 Client들의 함수를 호출하는 예제입니다. 서버측 코딩은 필요없고, [Install-dir]/applications/Tutorial3 폴더만 생성해 주시면 됩니다.  브라우져를 여러개 띄워두신다음 테스트 해보시면 됩니다. 이해를 위해 최소한의 코드만으로 만든 예제입니다. so=SharedObject.getRemote("soName", nc.uri, false); 의 'soName'은 SO를 구분짓는 이름이며, 이 이름에 묶여있는 SO에 연결된 클라이언트의 함수는 호출됩니다.  그리고 호출된 함수의 접근제한자는 public 이어야 합니다. 


* Client측 소스

 ...

 so=SharedObject.getRemote("soName", nc.uri, false);

 so.client=this;

 so.connect(nc);


 ...


 // SharedObject에 연결된 모든 Client의 'receiveMessage' 함수를 호출함.

 so.send("receiveMessage", "This is my message");


 ...

 // 접근제한자는 public이어야함.

 publicfunction receiveMessage(msg:String):void

 {

     Cc.log(msg);

 }

 ...

                           


Tutorial3.fxp




2. SharedObject에 연결된 다른 클라이언트의 함수 여러개 만들어 보기


  호출될 수 있는 함수를 여러개 만들어 보는 예제입니다. Object객체를 하나 만들어 주고, 그 객체의 속성에 함수를 넣어주고 SO의 client를 Object로 지정해주시면 됩니다. 이 예제또한 서버코딩이 필요없고, 예제 실행을 위해서는 [Install-dir]/applications/Tutorial4 폴더를 생성해 주어야 합니다.


* Client측 소스

 ...

 var obj:Object=new Object();

        

 obj.sayHi=function(msg:String):void

 {

     Cc.log(msg);

 };

                          

 obj.sayHello=function(msg:String):void

 {

     Cc.log(msg);

 };

 

 so.client=obj;

 ...

                           


Tutorial4.fxp


3. SharedObject를 이용해서 서버시간 구하기


   SharedObject를 이용해서 서버측에서 시간을 구한 후, SharedObject에 연결된 모든 클라이언트들에게 현재 시간을 알려주는 예제입니다. 서버사이드에서의 SO객체생성이 필요하며, setProperty() 함수를 이용해서 Data를 동기화 합니다. SO객체에 SyncEvent를 리스닝 하고있다, 동기화가 일어나면 SyncEvent가 송출되어 서버의 시간을 뿌려줍니다. 예제실행을 위해 서버측 모듈설정이 필요합니다.


* Server측 소스

 ...

 private ISharedObject _so;

       

 public void getServerTime(IClient client, RequestFunction function, AMFDataList params) {

     DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

     Date DateNow = new Date();

     _so.setProperty("currentTime", dateFormat.format(DateNow));

     getLogger().info(DateNow.getTime());

 }

 

 public void onAppStart(IApplicationInstance appInstance) {

      ISharedObjects sharedObjects = appInstance.getSharedObjects();

      _so = sharedObjects.getOrCreate("testSO");

      _so.acquire();

 }

 ...

   

* Client측 소스

 ...

 so.addEventListener(SyncEvent.SYNC, onSync);

 ...                 

 privatefunction onSync(event:SyncEvent):void

 {

      Cc.log("currentTime : " + so.data.currentTime);

 }        

 ...                 

 

Tutorial5.fxp

Tutorial5.java


[참고] Working with Shared Objects with Wowza and Flex

[참고] How to track users using a SharedObject


AND