2024 May. 01.
2023 Oct. 21.
2022 Feb. 26.
2021 Oct. 24.
2021 May 30.
2021 Apr. 07.
出典 EPGStation/doc/linux-setup.md at master · l3tnun/EPGStation · GitHub
関連ソフトの稼働確認
$ gcc --version $ node --version $ curl -o - http://<MirakurunURL>:<Port>/api/version ## 通常は curl -o - http://localhost:40772/api/version $ ffmpeg -version $ python --version $ ps ax | grep mysql | grep -v grep
node、Mirakurunのインストール
テレビ放送受信サーバーMirakurunを「Ubuntu/Arch系Manjaro Linux・PT2チューナー・DVBブロックデバイス」構成でインストール - rokkonet
pythonのインストール
pyenvをEPGStationを稼働させるユーザー(tvとした)でインストールする
出典 ubuntu 20.04 / 18.04 に pyenv をインストールする話 #Python - Qiita
$ su - tv $ sudo apt update && sudo apt install build-essential \ libffi-dev \ libssl-dev \ zlib1g-dev \ liblzma-dev \ libbz2-dev \ libreadline-dev \ libsqlite3-dev \ git $ git clone https://github.com/pyenv/pyenv.git ~/.pyenv $ echo 'export PYENV_ROOT="${HOME}/.pyenv"' >> ~/.profile $ echo 'export PATH="${PYENV_ROOT}/bin:${PATH}"' >> ~/.profile $ echo 'eval "$(pyenv init -)"' >> ~/.profile source ~/.profile
pyenvがインストールされていることを確認する
$ pyenv -v
インストールできるpythonの一覧を出力する
$ pyenv install --list
適当なバージョンのpythonをインストールする
$ pyenv install 3.9.4
インストールされたpythonを確認する
$ pyenv versions
tvユーザーでのpythonバージョンを当該ユーザー空間グローバルに設定する
$ pyenv global 3.9.4
mariadbのインストールとEPGStation向け設定
mariadbのEPGStation向け設定
出典 https://github.com/y-hashida/Memo_Mirakurun-and-EPGStation
・データベースとユーザーを作成し、大量発生するバイナリログの保管期間を1日にする
$ sudo mysql > CREATE DATABASE epgstation CHARACTER SET utf8; 2021 Oct. 24. CREATE DATABASE epgstation CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; の方がよいと思う。 COLLATE設定について https://qiita.com/tfunato/items/e48ad0a37b8244a788f6:title > GRANT ALL ON epgstation.* TO epgstation@localhost IDENTIFIED BY 'epgstation'; > GRANT ALL ON epgstation.* TO epgstation@127.0.0.1 IDENTIFIED BY 'epgstation'; > SET GLOBAL expire_logs_days = 1; > exit
EPGStationのインストール
出典 EPGStation/doc/linux-setup.md at master · l3tnun/EPGStation · GitHub
$ su - tv $ git clone https://github.com/l3tnun/EPGStation.git $ cd EPGStation $ npm run all-install $ npm run build $ cp config/config.sample.yml config/config.yml $ cp config/operatorLogConfig.sample.yml config/operatorLogConfig.yml $ cp config/epgUpdaterLogConfig.sample.yml config/epgUpdaterLogConfig.yml $ cp config/serviceLogConfig.sample.yml config/serviceLogConfig.yml
~/EPGStation/config/config.ymlを修正する
unix socket接続できなかったので、
unix socket接続設定を削除
40772ポートIP接続を設定
mysql利用に設定
録画ファイル名を設定
録画ファイル保存ディレクトリを設定
マニュアル EPGStation/doc/conf-manual.md at master · l3tnun/EPGStation · GitHub
# mirakurunPath: http+unix://%2Fvar%2Frun%2Fmirakurun.sock/ mirakurunPath: http://localhost:40772 # dbtype: sqlite # sqlite: # extensions: # - '/hoge/regexp.dylib' # regexp: true dbtype: mysql mysql: host: localhost port: 3306 user: epgstation password: epgstation database: epgstation recordedFormat: '%SHORTYEAR%%MONTH%%DAY%%HOUR%%MIN%%TYPE%%CH%-%SID%-%CHNAME%-%TITLE%' recorded: - name: recorded ## ブラウザ上に表示される保存場所名 path: '/RECORDED/DIR' ## 保存ディレクトリのフルパス #ffmpeg: /usr/local/bin/ffmpeg ffmpeg: /usr/bin/ffmpeg #ffprobe: /usr/local/bin/ffprobe ffprobe: /usr/bin/ffprobe
ポート開放
8888番ポートをLAN内に開放する
(例)
$ sudo ufw enable $ sudo ufw allow proto tcp from 192.168.1.0/24 to any port 8888 ## LAN $ sudo ufw allow proto udp from 192.168.1.0/24 to any port 8888 ## LAN $ sudo ufw allow proto tcp from 10.8.0.0/24 to any port 8888 ## openVPN $ sudo ufw allow proto udp from 10.8.0.0/24 to any port 8888 ## openVPN $ sudo ufw reload
自動起動設定(初回のみ行う)
$ cd ~/EPGStation $ sudo npm install pm2 -g $ sudo pm2 startup ubuntu $ pm2 start dist/index.js --name "epgstation" $ pm2 save
上記コマンド実行時の画面出力内容
$ sudo npm install pm2 -g /usr/local/bin/pm2 -> /usr/local/lib/node_modules/pm2/bin/pm2 /usr/local/bin/pm2-dev -> /usr/local/lib/node_modules/pm2/bin/pm2-dev /usr/local/bin/pm2-docker -> /usr/local/lib/node_modules/pm2/bin/pm2-docker /usr/local/bin/pm2-runtime -> /usr/local/lib/node_modules/pm2/bin/pm2-runtime npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.1 (node_modules/pm2/node_modules/chokidar/node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) + pm2@4.5.6 added 175 packages from 194 contributors in 15.996s $ sudo pm2 startup ubuntu Runtime Edition PM2 is a Production Process Manager for Node.js applications with a built-in Load Balancer. Start and Daemonize any application: $ pm2 start app.js Load Balance 4 instances of api.js: $ pm2 start api.js -i 4 Monitor in production: $ pm2 monitor Make pm2 auto-boot at server restart: $ pm2 startup To go further checkout: http://pm2.io/ ------------- [PM2] Init System found: systemd ----------------------------------------------------------- PM2 detected systemd but you precised ubuntu Please verify that your choice is indeed your init system If you arent sure, just run : pm2 startup ----------------------------------------------------------- Platform ubuntu Template [Unit] Description=PM2 process manager Documentation=https://pm2.keymetrics.io/ After=network.target [Service] Type=forking User=root LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin Environment=PM2_HOME=/root/.pm2 PIDFile=/root/.pm2/pm2.pid Restart=on-failure ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill [Install] WantedBy=multi-user.target Target path /etc/systemd/system/pm2-root.service Command list [ 'systemctl enable pm2-root' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-root.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-root... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-root.service → /etc/systemd/system/pm2-root.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 start dist/index.js --name "epgstation" Runtime Edition PM2 is a Production Process Manager for Node.js applications with a built-in Load Balancer. Start and Daemonize any application: $ pm2 start app.js Load Balance 4 instances of api.js: $ pm2 start api.js -i 4 Monitor in production: $ pm2 monitor Make pm2 auto-boot at server restart: $ pm2 startup To go further checkout: http://pm2.io/ ------------- [PM2] Spawning PM2 daemon with pm2_home=/HOME/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /HOME/EPGStation/dist/index.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ epgstation │ fork │ 0 │ online │ 0% │ 21.8mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘ $ pm2 save [PM2] Saving current process list... [PM2] Successfully saved in /HOME/.pm2/dump.pm2
EPGStationの稼働を http://localhost:8888 を開いて確認する。
PC再起動後、自動実行されなかったが、下記の 「自動起動した EPGStation の再起動(設定変更反映)」を行うと、PC再起動後自動実行された。
自動起動した EPGStation の再起動(設定変更反映)
## 出典 https://qiita.com/ikemura23/items/68fb61b16c6752daa7e8 $ cd ~/EPGStation $ pm2 stop epgstation $ pm2 start dist/index.js --name "epgstation" --update-env $ pm2 startup ## 画面出力された指示にしたがって、画面のコマンドをコピーする ## 上記でコピーしたコマンドを実行する $ sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u tv --hp ${HOME} $ pm2 save $ sudo reboot ## PCを再起動してEPGStationの自動起動を確認
稼働確認
- pm2コマンドで確認
$ pm2 status
- ブラウザで http://localhost:8888 を開いて確認
- mysqlのデータベーステーブルを確認
$ mysql -u epgstation -p epgstation > show tables; > select * from channel; > select * from program; > exit
ステータス表示
$ pm2 show epgstation
手動起動
$ npm start
手動終了
$ npm stop
ログ保管場所
${HOME}/EPGStation/logs/
${HOME}/.pm2/logs/epgstation-out.log
${HOME}/.pm2/logs/epgstation-error.log
ログファイルについて
GitHub - l3tnun/EPGStation: Mirakurun を使用した録画管理ソフト
config.yml詳細マニュアル
EPGStation/doc/conf-manual.md at master · l3tnun/EPGStation · GitHub
EPGStationのアンインストール
出典 EPGStationのインストール - にゃののん日記
$ pm2 delete epgstation ## PM2に登録されているEPGStationを削除 $ pm2 save ## PM2の現在の状態を保存 $ pm2 kill ## PM2を停止 $ sudo systemctl stop pm2-xxxxxxxx ## 現在のユーザ(xxxxxxxxをユーザ名に置き換える)でのPM2の自動起動を停止 $ sudo systemctl disable pm2-xxxxxxxx ## 現在のユーザでのPM2の無効化 $ sudo rm -f /etc/systemd/system/pm2-xxxxxxxx.service ## 設定を削除 $ rm -rf ~/.pm2 ## PM2の設定保存ディレクトリを削除
mysqlのテーブル構造
> show tables; +----------------------------+ | Tables_in_epgstation | +----------------------------+ | channel | | drop_log_file | | migrations | | program | | recorded | | recorded_history | | recorded_tag | | recorded_tags_recorded_tag | | reserve | | rule | | thumbnail | | video_file | +----------------------------+
> show columns from program; +----------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------------+--------------+------+-----+---------+-------+ | id | bigint(20) | NO | PRI | NULL | | | updateTime | bigint(20) | NO | | NULL | | | channelId | bigint(20) | NO | | NULL | | | eventId | bigint(20) | NO | | NULL | | | serviceId | int(11) | NO | | NULL | | | networkId | int(11) | NO | | NULL | | | startAt | bigint(20) | NO | | NULL | | | endAt | bigint(20) | NO | | NULL | | | startHour | int(11) | NO | | NULL | | | week | int(11) | NO | | NULL | | | duration | int(11) | NO | | NULL | | | isFree | tinyint(4) | NO | | NULL | | | name | text | NO | | NULL | | | halfWidthName | text | NO | | NULL | | | shortName | text | NO | | NULL | | | description | text | YES | | NULL | | | halfWidthDescription | text | YES | | NULL | | | extended | text | YES | | NULL | | | halfWidthExtended | text | YES | | NULL | | | genre1 | int(11) | YES | | NULL | | | subGenre1 | int(11) | YES | | NULL | | | genre2 | int(11) | YES | | NULL | | | subGenre2 | int(11) | YES | | NULL | | | genre3 | int(11) | YES | | NULL | | | subGenre3 | int(11) | YES | | NULL | | | channelType | varchar(255) | NO | | NULL | | | channel | varchar(255) | NO | | NULL | | | videoType | text | YES | | NULL | | | videoResolution | text | YES | | NULL | | | videoStreamContent | int(11) | YES | | NULL | | | videoComponentType | int(11) | YES | | NULL | | | audioSamplingRate | int(11) | YES | | NULL | | | audioComponentType | int(11) | YES | | NULL | | +----------------------+--------------+------+-----+---------+-------+
> show columns from recorded; +----------------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | reserveId | int(11) | YES | | NULL | | | ruleId | int(11) | YES | | NULL | | | programId | bigint(20) | YES | | NULL | | | channelId | bigint(20) | NO | | NULL | | | isProtected | tinyint(4) | NO | | 0 | | | startAt | bigint(20) | NO | | NULL | | | endAt | bigint(20) | NO | | NULL | | | duration | int(11) | NO | | NULL | | | name | text | NO | | NULL | | | halfWidthName | text | NO | | NULL | | | description | text | YES | | NULL | | | halfWidthDescription | text | YES | | NULL | | | extended | text | YES | | NULL | | | halfWidthExtended | text | YES | | NULL | | | genre1 | int(11) | YES | | NULL | | | subGenre1 | int(11) | YES | | NULL | | | genre2 | int(11) | YES | | NULL | | | subGenre2 | int(11) | YES | | NULL | | | genre3 | int(11) | YES | | NULL | | | subGenre3 | int(11) | YES | | NULL | | | videoType | text | YES | | NULL | | | videoResolution | text | YES | | NULL | | | videoStreamContent | int(11) | YES | | NULL | | | videoComponentType | int(11) | YES | | NULL | | | audioSamplingRate | int(11) | YES | | NULL | | | audioComponentType | int(11) | YES | | NULL | | | isRecording | tinyint(4) | NO | | NULL | | | dropLogFileId | int(11) | YES | UNI | NULL | | +----------------------+------------+------+-----+---------+----------------+ id:video_fileテーブルのrecordedIdと同じ値 startAt, endAt:unixタイムを1,000倍したミリ秒単位の数値。
> show columns from reserve; +-----------------------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------------------------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | updateTime | bigint(20) | NO | | NULL | | | ruleId | int(11) | YES | | NULL | | | ruleUpdateCnt | int(11) | YES | | NULL | | | isSkip | tinyint(4) | NO | | 0 | | | isConflict | tinyint(4) | NO | | 0 | | | allowEndLack | tinyint(4) | NO | | 0 | | | tags | text | YES | | NULL | | | isOverlap | tinyint(4) | NO | | 0 | | | isIgnoreOverlap | tinyint(4) | NO | | 0 | | | isTimeSpecified | tinyint(4) | NO | | 0 | | | parentDirectoryName | text | YES | | NULL | | | directory | text | YES | | NULL | | | recordedFormat | text | YES | | NULL | | | encodeMode1 | text | YES | | NULL | | | encodeParentDirectoryName1 | text | YES | | NULL | | | encodeDirectory1 | text | YES | | NULL | | | encodeMode2 | text | YES | | NULL | | | encodeParentDirectoryName2 | text | YES | | NULL | | | encodeDirectory2 | text | YES | | NULL | | | encodeMode3 | text | YES | | NULL | | | encodeParentDirectoryName3 | text | YES | | NULL | | | encodeDirectory3 | text | YES | | NULL | | | isDeleteOriginalAfterEncode | tinyint(4) | NO | | 0 | | | programId | bigint(20) | YES | | NULL | | | programUpdateTime | bigint(20) | YES | | NULL | | | channelId | bigint(20) | NO | | NULL | | | channel | text | NO | | NULL | | | channelType | text | NO | | NULL | | | startAt | bigint(20) | NO | | NULL | | | endAt | bigint(20) | NO | | NULL | | | name | text | YES | | NULL | | | halfWidthName | text | YES | | NULL | | | shortName | text | YES | | NULL | | | description | text | YES | | NULL | | | halfWidthDescription | text | YES | | NULL | | | extended | text | YES | | NULL | | | halfWidthExtended | text | YES | | NULL | | | genre1 | int(11) | YES | | NULL | | | subGenre1 | int(11) | YES | | NULL | | | genre2 | int(11) | YES | | NULL | | | subGenre2 | int(11) | YES | | NULL | | | genre3 | int(11) | YES | | NULL | | | subGenre3 | int(11) | YES | | NULL | | | videoType | text | YES | | NULL | | | videoResolution | text | YES | | NULL | | | videoStreamContent | int(11) | YES | | NULL | | | videoComponentType | int(11) | YES | | NULL | | | audioSamplingRate | int(11) | YES | | NULL | | | audioComponentType | int(11) | YES | | NULL | | +-----------------------------+------------+------+-----+---------+----------------+
> show columns from video_file; +---------------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | parentDirectoryName | text | NO | | NULL | | | filePath | text | NO | | NULL | | | type | text | NO | | NULL | | | name | text | NO | | NULL | | | size | bigint(20) | NO | | 0 | | | recordedId | int(11) | NO | MUL | NULL | | +---------------------+------------+------+-----+---------+----------------+ recordedId:recordedテーブルのidと同じ値
録画ファイル情報取得例
(例1)mysqlのデータから抽出
mysql > select video_file.id, video_file.parentDirectoryName, video_file.filePath, video_file.type, video_file.name, video_file.size, video_file.recordedId, recorded.startAt, recorded.endAt, recorded.name, recorded.description, recorded.extended from video_file LEFT OUTER JOIN recorded ON video_file.recordedId = recorded.id ;
(例2) config.ymlからの録画ファイル保存ディレクトリ取得 & mysqlデータ抽出
# visudo epgstationUser ALL=(root) NOPASSWD: /usr/bin/mysql $ su - epgstationUser $ ConfigFile="${HOME}/EPGStation/config/config.yml" $ ParentDir=$(cat "$ConfigFile" | grep -P '^[ \t]*path') $ ParentDir=${ParentDir#*\'} $ ParentDir=${ParentDir%\'*} $ ParentDir=${ParentDir%/} $ DestDir="DIR/TO/SAVE/RECORDED-FILE-LIST" $ DestFileName="FILE-NAME-OF-RECORDED-FILE-LIST" $ DbName=DATABE-NAME-OF-EPGSTATION-IN-MYSQL $ sed "s:${ParentDir}\t*:${ParentDir}/:" > "${DestDir}/${DestFileName}" <(echo "select video_file.id, '${ParentDir}' as parentDirPath, video_file.filePath, video_file.type, video_file.name, video_file.size, video_file.recordedId, recorded.startAt, recorded.endAt, recorded.name, recorded.description, recorded.extended from video_file LEFT OUTER JOIN recorded ON video_file.recordedId = recorded.id" | sudo /usr/bin/mysql -D ${DbName})
録画ファイル保存ディレクトリ
録画ファイル保存ディレクトリは、mysqlデータベースには"recorded"と記録されており、パスを取得できない。
録画ファイル保存ディレクトリパスは ~/EPGStation/config/config.yml内のrecorded: path: 'PARENT/DIR'を参照する。
録画ファイル情報テキストファイル保存スクリプト
スクリプト保管場所
https://bitbucket.org/arsmus/shell-script-public/src/master/audio-video/save_record-file-information-epgstation.sh
録画ファイル保存ディレクトリの変更について
- ~/EPGStation/config/config.yml内のrecorded: path: 'PARENT/DIR'を変更すると録画ファイル保存ディレクトリが変更される。
- 保存ディレクトリ変更前の録画ファイルは http://localhost:8888/ からは再生できなくなる。
録画ファイル変換(トランスコード)設定
設定記述ファイル:${USER}/EPGStation/config/config.yml
設定ブロック:encode:
設定記述:下記のように"- name:"で始め、変換コマンドjsファイル・拡張子・録画後タイムアウト時間(秒)を指定する。
2つの設定を記述した例
encode: - name: H.264 cmd: '%NODE% %ROOT%/config/enc.js' suffix: .mp4 rate: 4.0 - name: H.264-cut4secs cmd: '%NODE% %ROOT%/config/enc-cut4secs.js' suffix: .mp4 rate: 4.0
mpeg4変換スクリプト
デフォルト '%NODE% %ROOT%/config/enc.js'
const spawn = require('child_process').spawn; const ffmpeg = process.env.FFMPEG; const input = process.env.INPUT; const output = process.env.OUTPUT; const analyzedurationSize = '10M'; // Mirakurun の設定に応じて変更すること const probesizeSize = '32M'; // Mirakurun の設定に応じて変更すること const maxMuxingQueueSize = 1024; const dualMonoMode = 'main'; const videoHeight = parseInt(process.env.VIDEORESOLUTION, 10); const isDualMono = parseInt(process.env.AUDIOCOMPONENTTYPE, 10) == 2; const audioBitrate = videoHeight > 720 ? '192k' : '128k'; const preset = 'veryfast'; const codec = 'libx264'; const crf = 23; const args = ['-y', '-analyzeduration', analyzedurationSize, '-probesize', probesizeSize]; // dual mono 設定 if (isDualMono) { Array.prototype.push.apply(args, ['-dual_mono_mode', dualMonoMode]); } // input 設定 Array.prototype.push.apply(args,['-i', input]); // メタ情報を先頭に置く Array.prototype.push.apply(args,['-movflags', 'faststart']); // 字幕データを含めたストリームをすべてマップ // Array.prototype.push.apply(args, ['-map', '0', '-ignore_unknown', '-max_muxing_queue_size', maxMuxingQueueSize, '-sn']); // video filter 設定 let videoFilter = 'yadif'; if (videoHeight > 720) { videoFilter += ',scale=-2:720' } Array.prototype.push.apply(args, ['-vf', videoFilter]); // その他設定 Array.prototype.push.apply(args,[ '-preset', preset, '-aspect', '16:9', '-c:v', codec, '-crf', crf, '-f', 'mp4', '-c:a', 'aac', '-ar', '48000', '-ab', audioBitrate, '-ac', '2', output ]); let str = ''; for (let i of args) { str += ` ${ i }` } console.error(str); const child = spawn(ffmpeg, args); child.stderr.on('data', (data) => { console.error(String(data)); }); child.on('error', (err) => { console.error(err); throw new Error(err); }); process.on('SIGINT', () => { child.kill('SIGINT'); });
先頭4秒間カット・音声二重対応 '%NODE% %ROOT%/config/enc-cut4secs.js'
const spawn = require('child_process').spawn; const ffmpeg = process.env.FFMPEG; const input = process.env.INPUT; const output = process.env.OUTPUT; const analyzedurationSize = '10M'; // Mirakurun の設定に応じて変更すること const probesizeSize = '32M'; // Mirakurun の設定に応じて変更すること const maxMuxingQueueSize = 1024; const dualMonoMode = 'main'; const videoHeight = parseInt(process.env.VIDEORESOLUTION, 10); const isDualMono = parseInt(process.env.AUDIOCOMPONENTTYPE, 10) == 2; const audioBitrate = videoHeight > 720 ? '192k' : '128k'; const preset = 'veryfast'; const codec = 'libx264'; const crf = 23; const args = ['-ss', '4', '-y', '-analyzeduration', analyzedurationSize, '-probesize', probesizeSize]; // dual mono 設定 if (isDualMono) { Array.prototype.push.apply(args, ['-dual_mono_mode', dualMonoMode]); } // input 設定 Array.prototype.push.apply(args,['-i', input]); // メタ情報を先頭に置く Array.prototype.push.apply(args,['-movflags', 'faststart']); // 字幕データを含めたストリームをすべてマップ // Array.prototype.push.apply(args, ['-map', '0', '-ignore_unknown', '-max_muxing_queue_size', maxMuxingQueueSize, '-sn']); // video filter 設定 let videoFilter = 'yadif'; if (videoHeight > 720) { videoFilter += ',scale=-2:720' } Array.prototype.push.apply(args, ['-vf', videoFilter]); // その他設定 Array.prototype.push.apply(args,[ '-preset', preset, '-aspect', '16:9', '-c:v', codec, '-crf', crf, '-f', 'mp4', '-c:a', 'aac', '-ar', '48000', '-ab', audioBitrate, '-ac', '2', output ]); let str = ''; for (let i of args) { str += ` ${ i }` } console.error(str); const child = spawn(ffmpeg, args); child.stderr.on('data', (data) => { console.error(String(data)); }); child.on('error', (err) => { console.error(err); throw new Error(err); }); process.on('SIGINT', () => { child.kill('SIGINT'); });