Raspberry Pi 4でKonomiTV用にtsreplaceを使いたい+ハードウェアエンコもやりたい
タイトル通り。KonomiTVのβ0.12で録画視聴機能が実装されたので、tsreplaceでメタデータを保持したままmp4に圧縮して保存したい。
最新のtsreplace 0.12をwget→apt install
wget https://github.com/rigaya/tsreplace/releases/download/0.12/tsreplace_0.12_Ubuntu20.04_arm64.deb
sudo apt install ./tsreplace_0.12_Ubuntu20.04_arm64.deb
が、エラー
$ sudo apt install ./tsreplace_0.12_Ubuntu20.04_arm64.deb
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了
状態情報を読み取っています... 完了
注意、'./tsreplace_0.12_Ubuntu20.04_arm64.deb' の代わりに 'tsreplace' を選択します
インストールすることができないパッケージがありました。おそらく、あり得
ない状況を要求したか、(不安定版ディストリビューションを使用しているの
であれば) 必要なパッケージがまだ作成されていなかったり Incoming から移
動されていないことが考えられます。
以下の情報がこの問題を解決するために役立つかもしれません:
以下のパッケージには満たせない依存関係があります:
libavformat58 : 依存: libavcodec58 (= 8:4.3.6-0+deb11u1+rpt5)
依存: libsrt1.4-gnutls (>= 1.4.2) しかし、インストールすることができません
tsreplace : 依存: libavcodec58
依存: libavfilter7
E: 問題を解決することができません。壊れた変更禁止パッケージがあります。
とりあえず足りないものをインストールしてビルド
ここはChatGPTに頼ってたりする
sudo apt update
sudo apt install build-essential libavcodec-dev libavformat-dev libavfilter-dev
リポジトリクローンしてmake
git clone https://github.com/rigaya/tsreplace.git
cd tsreplace
make
sudo make install
入ったっぽい
xxxx@raspi:~/tsreplace $ tsreplace
ERROR: input file not set.
手動で依存関係解決したからビルドしなくてもdebファイルでインストールできたかも?
1分くらいのtsファイルを投げ込んでみる
このコマンドは公式リポジトリの使用例のまま
tsreplace -i input.m2ts -o output.m2ts -e ffmpeg -y -f mpegts -i - -copyts -start_at_zero -vf yadif -an -c:v libx264 -preset slow -crf 23 -g 90 -f mpegts -
ファイルサイズが小さくなっていることは確認できる
xxxx@raspi:~/tstest $ du -a
25444 ./output.m2ts
114492 ./input.m2ts
再生したいのでクライアントのWin11にVLCインストール中
正常に再生できた

データ放送も確認できた

今回はffmpegでソフトウェアエンコードしたが、ハードウェアエンコードが可能なら試したい
KonomiTVをアップデートしてみる
KonomiTVのインストーラー削除してたけどもう一回ダウンロードしてきたら行けた。
インストールされてるディレクトリを指定したら自動でやってくれる。
xxxx@raspi:~ $ ./KonomiTV-Installer-ARM.elf
────────────────────────────────────────────────────────── KonomiTV version 0.12.0 Installer ───────────────────────────────────────────────────────────
KonomiTV のインストール/アップデート/アンインストールを行うインストーラーです。
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 01. KonomiTV をインストールするときは 1 を、アップデートするときは 2 を、 │
│ アンインストールするときは 3 を入力してください。 │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
インストール(1) / アップデート(2) / アンインストール(3) [1/2/3] (1): 2
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 注意: このアップデーターは現時点では動作しない可能性があります。 │
│ KonomiTV は鋭意開発中のため、現在破壊的な構成変更が頻繁に行われています。 │
│ 破壊的変更が続く中アップデーターの機能を維持することは難しいため、 │
│ 安定版リリースまでの当面の間、アップデーターは最低限のメンテナンスのみ行っています。 │
│ もしアップデーターが動作しない場合は、適宜 DB や設定ファイルなどをバックアップの上で │
│ 一旦アンインストールし、新規でインストールし直していただきますようお願いいたします。 │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 02. アップデート対象の KonomiTV のフォルダのパスを入力してください。 │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 例: /opt/KonomiTV │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
アップデート対象の KonomiTV のフォルダのパス: /opt/KonomiTV
(以下略)
クライアントはアップデート後に更新されるまでちょっと待つかもしれない
データ解析とかサムネイル作成とかでとんでもなく重い処理が動いてるのか、SSHもpingも通らなくなった
再起動した
ハードウェアエンコードは思ってたより簡単
libx264をh264_v4l2m2mに書き換えるだけ
tsreplace -i input.m2ts -o output_he.m2ts -e ffmpeg -y -f mpegts -i - -copyts -start_at_zero -an -c:v h264_v4l2m2m -flags +ildct+ilme -preset slow -crf 23 -g 90 -f mpegts -
けど画質とアス比がおかしい

アス比は -vf で指定すると治った
tsreplace -i input.m2ts -o output_he_1280.m2ts -e ffmpeg -y -f mpegts -i - -copyts -start_at_zero -vf scale=1920:1080 -an -c:v h264_v4l2m2m -flags +ildct+ilme -preset slow -crf 23 -g 90 -f mpegts -
こうなるとKonomiTVでのストリーム用のエンコーダーにffmpegのh264_v4l2m2を指定したい
ここか?
EPGStationからのエンコードをv4l2とかtsreplaceにしようとしてるけど全くうまくいかない
docker-mirakurun-epgstationで動かしてるのでコンテナ内に関係ファイルを入れないと動かない
できねえ
コンテナにtsreplaceのバイナリマウントとaptで依存関係のインストールはした
うーんdocker execからtsreplaceは動くんだけどな
bashファイル作ってそれを実行する形にしてみる
#!/bin/bash
# エラーがあれば即終了
set -e
# ログ出力(任意)
echo "[enc-tsreplace.sh] Start encoding"
echo "INPUT: $INPUT"
echo "OUTPUT: $OUTPUT"
echo "FFMPEG: $FFMPEG"
# tsreplace + ffmpeg でエンコード
/usr/local/bin/tsreplace \
-i "$INPUT" \
-o "$OUTPUT" \
-e "$FFMPEG" \
-y -f mpegts -i - \
-copyts -start_at_zero \
-vf yadif -an \
-c:v libx264 -preset slow -crf 23 -g 90 \
-f mpegts -
# 完了ログ
echo "[enc-tsreplace.sh] Done encoding"
- name: H.264(tsreplace)
cmd: '/bin/bash %ROOT%/config/enc-tsreplace.sh'
suffix: .m2ts
rate: 4.0
きたかも
やっぱりlibx264だと遅い
結論としてはbashファイル経由ならtsreplaceがEPGStationの自動エンコードで使えそう
h264_v4l2m2mはまだ時間が必要
mirakurunのアップデートのついでにDockerfileを修正して、一発でtsrepalceとh264_v4l2m2mが使えるようにした。DockerfileはGPT-4oとの合作。
参考
FROM l3tnun/epgstation:master-debian
ENV DEV="make gcc git g++ automake wget autoconf build-essential libass-dev libfreetype6-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo zlib1g-dev"
ENV FFMPEG_VERSION=7.0
RUN apt-get update && \
apt-get -y install curl && \
apt-get -y install $DEV && \
apt-get -y install yasm libx264-dev libmp3lame-dev libopus-dev libvpx-dev && \
apt-get -y install libx265-dev libnuma-dev && \
apt-get -y install libasound2 libass9 libvdpau1 libva-x11-2 libva-drm2 libxcb-shm0 libxcb-xfixes0 libxcb-shape0 libvorbisenc2 libtheora0 libaribb24-dev && \
apt-get -y install libavcodec-dev libavformat-dev libavfilter-dev && \
\
mkdir /tmp/ffmpeg_sources && \
cd /tmp/ffmpeg_sources && \
curl -fsSL http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 | tar -xj --strip-components=1 && \
./configure \
--prefix=/usr/local \
--disable-shared \
--pkg-config-flags=--static \
--enable-gpl \
--enable-libass \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libopus \
--enable-libtheora \
--enable-libvorbis \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-version3 \
--enable-libaribb24 \
--enable-nonfree \
--disable-debug \
--disable-doc \
&& \
make -j$(nproc) && \
make install && \
\
# tsreplace ソースからビルド
cd /opt && \
git clone https://github.com/rigaya/tsreplace.git && \
cd tsreplace && \
make -j$(nproc) && \
make install && \
\
# 後始末
apt-get -y remove $DEV && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /tmp/* && \
rm -rf /opt/tsreplace
tsreplaceは例によってコンテナ内でビルドしてる
あとはm2ts録画ファイルの(1)をどうにか直す
ハードウェア縁故なんとかうまくいかないかなーストリームだけでも
各エンコードファイルもまとめておこうかな
ソフトウェアエンコ用はjsファイル、ワードウェアエンコ用はシェルスクリプト?で書いた
プログレスバーが表示されないのも直したい
ソフトウェアエンコ
・enc.js(ffmpeg/libx264)
・enc-tsreplace.sh(tsreplace/libx264)
ハードウェアエンコ
・enc-hwe.js(ffmpeg/h264_v4l2m2m)
・enc-hwe-tsreplace.sh(tsreplace/h264_v4l2m2m)
全部どっちかのファイル形式にまとめたい。あとハードウェアエンコは現時点では映像が壊れる。
これはほぼデフォルト
const spawn = require('child_process').spawn;
const execFile = require('child_process').execFile;
const ffmpeg = process.env.FFMPEG;
const ffprobe = process.env.FFPROBE;
const input = process.env.INPUT;
const output = process.env.OUTPUT;
const isDualMono = parseInt(process.env.AUDIOCOMPONENTTYPE, 10) == 2;
const args = ['-y'];
/**
* 動画長取得関数
* @param {string} filePath ファイルパス
* @return number 動画長を返す (秒)
*/
const getDuration = filePath => {
return new Promise((resolve, reject) => {
execFile(ffprobe, ['-v', '0', '-show_format', '-of', 'json', filePath], (err, stdout) => {
if (err) {
reject(err);
return;
}
try {
const result = JSON.parse(stdout);
resolve(parseFloat(result.format.duration));
} catch (err) {
reject(err);
}
});
});
};
// 字幕用
Array.prototype.push.apply(args, ['-fix_sub_duration']);
// input 設定
Array.prototype.push.apply(args, ['-i', input]);
// ビデオストリーム設定
Array.prototype.push.apply(args, ['-map', '0:v', '-c:v', 'libx264']);
// インターレス解除
Array.prototype.push.apply(args, ['-vf', 'yadif']);
// オーディオストリーム設定
if (isDualMono) {
Array.prototype.push.apply(args, [
'-filter_complex',
'channelsplit[FL][FR]',
'-map', '[FL]',
'-map', '[FR]',
'-metadata:s:a:0', 'language=jpn',
'-metadata:s:a:1', 'language=eng',
'-ac', '1',
]);
} else {
Array.prototype.push.apply(args, ['-map', '0:a']);
}
Array.prototype.push.apply(args, ['-c:a', 'aac']);
// 字幕ストリーム設定
Array.prototype.push.apply(args, ['-map', '0:s?', '-c:s', 'mov_text']);
// 品質設定
Array.prototype.push.apply(args, ['-preset', 'veryfast', '-crf', '26']);
// 出力ファイル
Array.prototype.push.apply(args, [output]);
(async () => {
// 進捗計算のために動画の長さを取得
const duration = await getDuration(input);
const child = spawn(ffmpeg, args);
child.stderr.on('data', data => {
let strbyline = String(data).split('\n');
for (let i = 0; i < strbyline.length; i++) {
let str = strbyline[i];
if (str.startsWith('frame')) {
const progress = {};
const ffmpeg_reg = /frame=\s*(?<frame>\d+)\sfps=\s*(?<fps>\d+(?:\.\d+)?)\sq=\s*(?<q>[+-]?\d+(?:\.\d+)?)\sL?size=\s*(?<size>\d+(?:\.\d+)?)(kB|KiB)\stime=\s*(?<time>\d+[:\.\d+]*)\sbitrate=\s*(?<bitrate>\d+(?:\.\d+)?)kbits\/s(?:\sdup=\s*(?<dup>\d+))?(?:\sdrop=\s*(?<drop>\d+))?\sspeed=\s*(?<speed>\d+(?:\.\d+)?)x/;
let ffmatch =str.match(ffmpeg_reg);
if (ffmatch === null) continue;
progress['frame'] = parseInt(ffmatch.groups.frame);
progress['fps'] = parseFloat(ffmatch.groups.fps);
progress['q'] = parseFloat(ffmatch.groups.q);
progress['size'] = parseInt(ffmatch.groups.size);
progress['time'] = ffmatch.groups.time;
progress['bitrate'] = parseFloat(ffmatch.groups.bitrate);
progress['dup'] = ffmatch.groups.dup == null ? 0 : parseInt(ffmatch.groups.dup);
progress['drop'] = ffmatch.groups.drop == null ? 0 : parseInt(ffmatch.groups.drop);
progress['speed'] = parseFloat(ffmatch.groups.speed);
let current = 0;
const times = progress.time.split(':');
for (let i = 0; i < times.length; i++) {
if (i == 0) {
current += parseFloat(times[i]) * 3600;
} else if (i == 1) {
current += parseFloat(times[i]) * 60;
} else if (i == 2) {
current += parseFloat(times[i]);
}
}
// 進捗率 1.0 で 100%
const percent = current / duration;
const log =
'frame= ' +
progress.frame +
' fps=' +
progress.fps +
' size=' +
progress.size +
' time=' +
progress.time +
' bitrate=' +
progress.bitrate +
' drop=' +
progress.drop +
' speed=' +
progress.speed;
console.log(JSON.stringify({ type: 'progress', percent: percent, log: log }));
}
}
});
child.on('error', err => {
console.error(err);
throw new Error(err);
});
child.on('close', (code) => {
process.exitCode = code;
});
process.on('SIGINT', () => {
child.kill('SIGINT');
});
})();
tsreplace経由のソフトウェアエンコ
エンコードはできるけどtmpのあたりは修正するかも
#!/bin/bash
set -e
echo "[enc-tsreplace.sh] Start encoding"
echo "INPUT: $INPUT"
echo "OUTPUT: $OUTPUT"
echo "FFMPEG: $FFMPEG"
# 一時ファイル名を作成(例: 元のファイル名の末尾に .tmp)
TEMP_OUTPUT="${OUTPUT}.tmp"
# tsreplace + ffmpeg でエンコードして一時ファイルに出力
/usr/local/bin/tsreplace \
-i "$INPUT" \
-o "$TEMP_OUTPUT" \
-e "$FFMPEG" \
-y -f mpegts -i - \
-copyts -start_at_zero \
-vf yadif -an \
-c:v libx264 -preset ultrafast -crf 23 -g 90 \
-f mpegts -
# 成功したら一時ファイルを元のファイルに上書き
mv "$TEMP_OUTPUT" "$OUTPUT"
echo "[enc-tsreplace.sh] Done encoding"
ffmpegのみ用とtsreplace経由用のハードウェアエンコファイルは動作しないから直ったら貼る
次はKonomiTVのストリーム用にHWE使ってみたい