OpenCV의 연산의 결과물은 일반적으로 Mat이라는 일종의 매트릭스 구조체로 표현된다. 보통의 경우 이 Mat 내용은 로컬 컴퓨터에서 실시간으로 윈도우를 통해 보여주거나, 파일에 저장한 후 프로세싱이 끝난 뒤 사용자에게 전달하는 방식을 사용하고 있다. 하지만 실시간으로, 원격에 있는 사용자에게, 웹을 통해 스트리밍을 하려는 조건이 주어지면 문제는 간단하게 해결되지는 않는다.
OpenCV VideoWriter()
OpenCV에서는 VideoWriter()를 이용해서 미디어 파일을 생성할 수 있으며 이때 파일명, 코덱, 속도 등을 지정할 수 있다. 아래의 코드는 로컬 카메라로 부터 스트림을 읽어서 윈도우에 표시하고 동시에 out.avi라는 파일에 저장하는 예이다.

VideoCapture cam(0);
VideoWriter video("out.avi", ...);
Mat frame;
loop {
  cap >> frame;
  video.write(frame);
  imshow("Local", frame);
  waitKey();
}
피드(Feed) 생성
ffmpeg 명령어로 이 미디어 파일(out.avi)을 입력으로 해서 ffserver에 공급할 피드를 생성하는 방식은 아래와 같다.
ffmpeg -i out.avi http://localhost:8090/feed1.ffm
이 방식은 두 가지의 문제를 갖고 있는데 첫째는 동일한 파일에 대해 한쪽에서는 쓰고, 다른 한쪽에서는 읽는 과정이 반복되기 때문에 퍼포먼스에 문제가 발생하는 점이며, 두번째 문제는 out.avi 파일 크기가 계속적으로 증가한다는 점이다. 이 문제를 해결하기 위해 일반 파일 대신 Named FIFO를 사용한다.
Named FIFO
Named FIFO는 파이프(pipe)의 한 종류로, 두 프로세스간에 한쪽에서 쓰면 다른 한쪽에서는 순서대로 읽어내는 기능을 제공하기 위해 고안되었다. 앞에 Named가 붙는 이유는 마치 이름이 있는 파일처럼 보이기 때문이다. 같은 이름을 가진 일반 파일이 있다면 이를 제거하고 Named FIFO를 생성한다. rm out.avi
mkfifo out.avi
한가지 알아두어야 할 점은 Named FIFO는 읽기/쓰기간에 블럭(Blocking on Read/Write)이 된다는 점이다. 즉, OpenCV 프로그램은 FIFO에 write 후, 다른 쪽에서 Read 할때까지 Blocking 상태를 유지하게 된다. 반드시 ffmpeg -i out.avi http://localhost:8090/feed1.ffm가 실행되고 FIFO를 읽어 가야만 Blocking이 해제된다.
ffserver에서 스트리밍
이제 ffserver는 http://localhost:8090/feed1.ffm 피드를 받아서 스트림을 만들어 내면 된다. ffserver에서 피드와 스트림을 구성하는 방법은 이 글을 참조한다.
[번외 #1] FFMpeg과 OpenCV에서 Webcam을 같이 열기
ffmpeg -f v4l2 -i /dev/video0 -codec copy -f v4l2 /dev/video1 위와 같이 ffmpeg 유틸리티를 사용해서 /dev/video0로 부터 /dev/video1을 생성한 후, OpenCV에서 /dev/video1을 액세스한다.

VideoCapture capture
capture.open(1)
[번외 #2] /dev/video0로 부터 /dev/video1와 ffserver feeder 동시 생성
ffmpeg -f v4l2 -i /dev/video0 -codec copy -f v4l2 /dev/video1 http://localhost:8090/feed1.html