RasPi上にLive Streaming 環境(保存つき)を作る その1:お手本先行プロジェクトをきめる

遠隔でRasPi上にLive Streaming 環境(保存つき)を作る必要ができたので技術調査がてら。

まるでメディア系に興味をもたず来たので、色々下調べしたところ
実装も軽く、意図した構成にちかい以下の動画を見つけました。
www.youtube.com

これからしばらく、この動画のコードを読んだり部分実行したりして勉強しようと思います。

実際のところ

では早速中身をみてみます。

まずはメインの実行スクリプトcam-rec-strm.shから。

#!/bin/bash

while [ 1 ]
do
raspivid -o - -t 0 -hf -vf -w 1080 -h 768 -fps 20 | ./split.o | cvlc -vvv stream:///dev/stdin --sout '#standard{access=http,mux=ts,dst=:8160}' :demux=h264 &
sleep $1
kill $!
done

raspividはRaspbian標準のカメラポートから動画をとるコマンドです。


Cの方(split.c)はこんな感じ。
……一応C言語使ってる方だと思ってたのですが
知らんライブラリがありますね……??

/* This file implements a data splitter
 * for data coming in to STDIN.
 * Data is split to be written to a 
 * file as well as written back out
 * to STDOUT for streaming.
 *
 * All code provided is as is and
 * is not fully tested.
 *
 * Author: Aadil Rizvi
 * Date Created: 11/25/2016
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stropts.h>
#include <signal.h>

#define MAX_FILENAME_SIZE 100

//File descriptor for currently open data file
static int fd_out;

void sig_handler(int signum) {

  if (fd_out >= 0) {    
    // Flush all write queues
    ioctl(fd_out, I_FLUSH, FLUSHW);

    // Close data file
    close(fd_out);
  }

  exit(0);
}

int main(void) {
  char in_array[1024];
  int nBytes;
  char filename[MAX_FILENAME_SIZE];
  struct timeval ts;  

  // Register signal handler
  signal(SIGINT, sig_handler);

  // Initialize fd_out
  fd_out = -1;

  // Get current time for unique filename
  gettimeofday(&ts, NULL);

  // Generate filename
  snprintf(filename, MAX_FILENAME_SIZE, "raspiVid-%u-%u.h264", ts.tv_sec, ts.tv_usec);

  // Open file to write data
  fd_out = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

  // Read data from STDIN
  nBytes = read(STDIN_FILENO, in_array, sizeof(in_array));

  // Read data from stdin in a loop
  // while writing data to file and
  // stdout as well
  while(nBytes > 0) {

    // Write data to file
    write(fd_out, (const void*)in_array, nBytes);

    // Write data to stdout as well
    write(STDOUT_FILENO, (const void*)in_array, nBytes);

    // Flush all write queues
    ioctl(fd_out, I_FLUSH, FLUSHW);

    // Read next available chunk of data from stdin
    nBytes = read(STDIN_FILENO, in_array, sizeof(in_array)); 
  }

  // Close data file
  close(fd_out);
  fd_out = -1;

  return 0;
}

cvlcはVLCちう動画再生ソフトについてくるサブコマンドでVLCGUIなし版。
画像におけるImageMagickめいた立場の使い方で、CLI上でメディアデータを取り扱いできるようです。