duo_splitter 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.ja.md +128 -0
- data/README.md +13 -11
- data/exe/duo_splitter +9 -3
- data/lib/duo_splitter.rb +39 -10
- data/lib/duo_splitter/batch_processor.rb +36 -0
- data/lib/duo_splitter/commands/base_command.rb +121 -0
- data/lib/duo_splitter/commands/overlapping_command.rb +37 -0
- data/lib/duo_splitter/commands/repeating_command.rb +38 -0
- data/lib/duo_splitter/commands/split_command.rb +31 -0
- data/lib/duo_splitter/context.rb +34 -0
- data/lib/duo_splitter/encoders/aac_encoder.rb +17 -0
- data/lib/duo_splitter/encoders/base_encoder.rb +57 -0
- data/lib/duo_splitter/encoders/mp3_encoder.rb +17 -0
- data/lib/duo_splitter/encoders/wav_encoder.rb +17 -0
- data/lib/duo_splitter/models/album.rb +23 -0
- data/lib/duo_splitter/models/section.rb +38 -0
- data/lib/duo_splitter/models/sentence.rb +35 -0
- data/lib/duo_splitter/runner.rb +43 -64
- data/lib/duo_splitter/services/create_overlapping_sentences.rb +19 -0
- data/lib/duo_splitter/services/create_repeating_sentences.rb +20 -0
- data/lib/duo_splitter/services/create_sentences.rb +18 -0
- data/lib/duo_splitter/services/support/base_concatenate.rb +46 -0
- data/lib/duo_splitter/services/support/create_blank_sentences.rb +40 -0
- data/lib/duo_splitter/services/support/encode.rb +23 -0
- data/lib/duo_splitter/services/support/overlapping_concatenate.rb +19 -0
- data/lib/duo_splitter/services/support/repeating_concatenate.rb +22 -0
- data/lib/duo_splitter/services/support/split_tracks.rb +42 -0
- data/lib/duo_splitter/temp_dir_wrapper.rb +20 -0
- data/lib/duo_splitter/version.rb +3 -1
- metadata +34 -15
- data/lib/duo_splitter/aac_encoder.rb +0 -13
- data/lib/duo_splitter/album.rb +0 -21
- data/lib/duo_splitter/encoder.rb +0 -71
- data/lib/duo_splitter/mp3_encoder.rb +0 -13
- data/lib/duo_splitter/section.rb +0 -30
- data/lib/duo_splitter/sentence.rb +0 -22
- data/lib/duo_splitter/wav_encoder.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc561bd757c37766b2d291595d13e381b663fc762a1e787192ef742e4866f45e
|
4
|
+
data.tar.gz: 39e5095aaf66aed68a33208dcac788261abfaba3e40eaefe36513df835121c36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6846d989928dca0332a2756f5c6a66897c6ace7245042eb33abb53e36801adc473639c268ec59748f68081fe7d739a8958e7473e2c18e2c26c58f14a6858bc2
|
7
|
+
data.tar.gz: 842e11082d13c649df3bf9d84278df5466634996b01ae178f9d1ca7f509882648c1c548428546a9273d4422ff5d3fce5f7860a51a67ebe87cd271e7a68f70121
|
data/README.ja.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# duo\_splitter
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/healthypackrat/duo_splitter.svg?branch=master)](https://travis-ci.org/healthypackrat/duo_splitter)
|
4
|
+
|
5
|
+
このgemに含まれているコマンドで[DUO 3.0 CD/**復習用**](https://www.amazon.co.jp/dp/4900790079)の音声を例文ごとに分割できます。
|
6
|
+
|
7
|
+
## 必要なもの
|
8
|
+
|
9
|
+
- `ffmpeg`
|
10
|
+
- `brew install ffmpeg`でインストールしてください
|
11
|
+
- `sox`
|
12
|
+
- `brew install sox`でインストールしてください
|
13
|
+
- `repeating`コマンドと`overlapping`コマンドを実行する際に必要です
|
14
|
+
|
15
|
+
## インストール
|
16
|
+
|
17
|
+
```
|
18
|
+
$ gem install duo_splitter
|
19
|
+
```
|
20
|
+
|
21
|
+
## 使い方
|
22
|
+
|
23
|
+
### 準備
|
24
|
+
|
25
|
+
1. WAVエンコーダを指定してCDをiTunesにインポートしてください。
|
26
|
+
2. ターミナルを開いてインポートしたトラックがあるディレクトリへ移動してください。
|
27
|
+
|
28
|
+
### 単純な分割
|
29
|
+
|
30
|
+
以下のコマンドを実行すると`~/Desktop/DUO 3.0`に分割された音声が生成されます。
|
31
|
+
|
32
|
+
```
|
33
|
+
$ duo_splitter split *.wav
|
34
|
+
```
|
35
|
+
|
36
|
+
指定できるオプションを確認するには`duo_splitter split -h`を実行してください。
|
37
|
+
|
38
|
+
出力ディレクトリを変更するには`-d`オプションを指定してください:
|
39
|
+
|
40
|
+
```
|
41
|
+
$ duo_splitter split -d /path/to/dir *.wav
|
42
|
+
```
|
43
|
+
|
44
|
+
出力フォーマットを変更するには`-f`オプションを指定してください:
|
45
|
+
|
46
|
+
```
|
47
|
+
$ duo_splitter split -f mp3 *.wav
|
48
|
+
```
|
49
|
+
|
50
|
+
「SECTION 〜」の音声が不要な場合は`--no-output-intro`オプションを指定してください:
|
51
|
+
|
52
|
+
```
|
53
|
+
$ duo_splitter split --no-output-intro *.wav
|
54
|
+
```
|
55
|
+
|
56
|
+
出力されるファイル名にセクション番号を付けたくない場合は`--no-section-number`オプションを指定してください:
|
57
|
+
|
58
|
+
```
|
59
|
+
$ duo_splitter split --no-section-number *.wav
|
60
|
+
```
|
61
|
+
|
62
|
+
`ffmpeg`の場所を変更するには`--ffmpeg-path`オプションを指定してください:
|
63
|
+
|
64
|
+
```
|
65
|
+
$ duo_splitter split --ffmpeg-path=/path/to/ffmpeg *.wav
|
66
|
+
```
|
67
|
+
|
68
|
+
### リピーティング用の分割
|
69
|
+
|
70
|
+
以下のコマンドを実行すると`~/Desktop/DUO 3.0 (Repeating)`に分割された音声が生成されます。
|
71
|
+
|
72
|
+
```
|
73
|
+
$ duo_splitter repeating *.wav
|
74
|
+
```
|
75
|
+
|
76
|
+
生成された音声の最後には合図の音声と例文と同じ長さの無音の音声が追加されています。
|
77
|
+
|
78
|
+
指定できるオプションを確認するには`duo_splitter repeating -h`を実行してください。
|
79
|
+
|
80
|
+
合図の音声が不要な場合は`--no-notification-sound`オプションを指定してください:
|
81
|
+
|
82
|
+
```
|
83
|
+
$ duo_splitter repeating --no-notification-sound *.wav
|
84
|
+
```
|
85
|
+
|
86
|
+
合図の音声を変更するには`--notification-sound-path`オプションを指定してください:
|
87
|
+
|
88
|
+
```
|
89
|
+
$ duo_splitter repeating --notification-sound-path=/path/to/audio.wav *.wav
|
90
|
+
```
|
91
|
+
|
92
|
+
`sox`の場所を変更するには`--sox-path`オプションを指定してください:
|
93
|
+
|
94
|
+
```
|
95
|
+
$ duo_splitter repeating --sox-path=/path/to/sox *.wav
|
96
|
+
```
|
97
|
+
|
98
|
+
### オーバーラッピング用の分割
|
99
|
+
|
100
|
+
以下のコマンドを実行すると`~/Desktop/DUO 3.0 (Overlapping)`に分割された音声が生成されます。
|
101
|
+
|
102
|
+
```
|
103
|
+
$ duo_splitter overlapping *.wav
|
104
|
+
```
|
105
|
+
|
106
|
+
生成された音声の先頭には合図の音声が追加されています。
|
107
|
+
|
108
|
+
指定できるオプションを確認するには`duo_splitter overlapping -h`を実行してください。
|
109
|
+
|
110
|
+
合図の音声を変更するには`--notification-sound-path`オプションを指定してください:
|
111
|
+
|
112
|
+
```
|
113
|
+
$ duo_splitter overlapping --notification-sound-path=/path/to/audio.wav *.wav
|
114
|
+
```
|
115
|
+
|
116
|
+
`sox`の場所を変更するには`--sox-path`オプションを指定してください:
|
117
|
+
|
118
|
+
```
|
119
|
+
$ duo_splitter overlapping --sox-path=/path/to/sox *.wav
|
120
|
+
```
|
121
|
+
|
122
|
+
## 開発
|
123
|
+
|
124
|
+
テストするには`bundle install`を実行してから`bin/rspec`を実行してください。
|
125
|
+
|
126
|
+
## ライセンス
|
127
|
+
|
128
|
+
ライセンスは[MIT License](https://opensource.org/licenses/MIT)です。
|
data/README.md
CHANGED
@@ -1,6 +1,15 @@
|
|
1
|
-
|
1
|
+
[Read this README in Japanese (日本語で読む)](README.ja.md)
|
2
2
|
|
3
|
-
|
3
|
+
# duo\_splitter
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/healthypackrat/duo_splitter.svg?branch=master)](https://travis-ci.org/healthypackrat/duo_splitter)
|
6
|
+
|
7
|
+
This gem provides a command to split the tracks into each sentences from [DUO 3.0 CD](https://www.amazon.co.jp/dp/4900790079).
|
8
|
+
|
9
|
+
## Requirements
|
10
|
+
|
11
|
+
- `ffmpeg`
|
12
|
+
- `sox`
|
4
13
|
|
5
14
|
## Installation
|
6
15
|
|
@@ -10,18 +19,11 @@ $ gem install duo_splitter
|
|
10
19
|
|
11
20
|
## Usage
|
12
21
|
|
13
|
-
|
14
|
-
Usage: duo_splitter [options] "01 Track 01.wav" "02 Track 02.wav" ... "45 Track 45.wav"
|
15
|
-
-d, --output-dir=PATH Output directory (default: /Users/yzn/Desktop/DUO 3.0)
|
16
|
-
-f, --format=FORMAT Output format (default: wav; one of aac, mp3, wav)
|
17
|
-
--[no-]output-intro Output intro track (default: true)
|
18
|
-
--[no-]section-number Add section number to output name (default: true)
|
19
|
-
--ffmpeg-path=PATH Path to ffmpeg command (default: ffmpeg)
|
20
|
-
```
|
22
|
+
(To be documented)
|
21
23
|
|
22
24
|
## Development
|
23
25
|
|
24
|
-
Run `bin/rspec` to run the specs
|
26
|
+
Run `bin/rspec` to run the specs after running `bundle install`.
|
25
27
|
|
26
28
|
## Contributing
|
27
29
|
|
data/exe/duo_splitter
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
+
require 'duo_splitter'
|
4
5
|
|
5
|
-
|
6
|
-
runner.
|
6
|
+
begin
|
7
|
+
runner = DuoSplitter::Runner.new(ARGV)
|
8
|
+
runner.run
|
9
|
+
rescue DuoSplitter::Error => e
|
10
|
+
warn e.message
|
11
|
+
exit 1
|
12
|
+
end
|
data/lib/duo_splitter.rb
CHANGED
@@ -1,22 +1,51 @@
|
|
1
|
-
|
2
|
-
require "duo_splitter/section"
|
3
|
-
require "duo_splitter/sentence"
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require "duo_splitter/wav_encoder"
|
3
|
+
require 'duo_splitter/models/album'
|
4
|
+
require 'duo_splitter/models/section'
|
5
|
+
require 'duo_splitter/models/sentence'
|
9
6
|
|
10
|
-
require
|
7
|
+
require 'duo_splitter/batch_processor'
|
11
8
|
|
12
|
-
require
|
9
|
+
require 'duo_splitter/context'
|
10
|
+
|
11
|
+
require 'duo_splitter/temp_dir_wrapper'
|
12
|
+
|
13
|
+
require 'duo_splitter/encoders/base_encoder'
|
14
|
+
require 'duo_splitter/encoders/aac_encoder'
|
15
|
+
require 'duo_splitter/encoders/mp3_encoder'
|
16
|
+
require 'duo_splitter/encoders/wav_encoder'
|
17
|
+
|
18
|
+
require 'duo_splitter/services/support/base_concatenate'
|
19
|
+
require 'duo_splitter/services/support/repeating_concatenate'
|
20
|
+
require 'duo_splitter/services/support/overlapping_concatenate'
|
21
|
+
|
22
|
+
require 'duo_splitter/services/support/create_blank_sentences'
|
23
|
+
require 'duo_splitter/services/support/encode'
|
24
|
+
require 'duo_splitter/services/support/split_tracks'
|
25
|
+
|
26
|
+
require 'duo_splitter/services/create_sentences'
|
27
|
+
require 'duo_splitter/services/create_repeating_sentences'
|
28
|
+
require 'duo_splitter/services/create_overlapping_sentences'
|
29
|
+
|
30
|
+
require 'duo_splitter/runner'
|
31
|
+
|
32
|
+
require 'duo_splitter/commands/base_command'
|
33
|
+
require 'duo_splitter/commands/split_command'
|
34
|
+
require 'duo_splitter/commands/repeating_command'
|
35
|
+
require 'duo_splitter/commands/overlapping_command'
|
36
|
+
|
37
|
+
require 'duo_splitter/version'
|
13
38
|
|
14
39
|
require 'pathname'
|
15
40
|
|
16
41
|
module DuoSplitter
|
17
42
|
class Error < StandardError; end
|
18
43
|
|
19
|
-
|
44
|
+
ROOT_DIR = Pathname.new(__dir__).parent
|
45
|
+
|
46
|
+
ASSETS_DIR = ROOT_DIR.join('assets')
|
47
|
+
|
48
|
+
DATA_DIR = ROOT_DIR.join('data')
|
20
49
|
|
21
50
|
NUMBER_OF_SECTIONS = 45
|
22
51
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
|
5
|
+
module DuoSplitter
|
6
|
+
class BatchProcessor
|
7
|
+
def initialize(message:, show_progress: true)
|
8
|
+
@message = message
|
9
|
+
@show_progress = show_progress
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(commands)
|
13
|
+
commands.each.with_index(1) do |command, index|
|
14
|
+
print_progress "#{@message} #{index}/#{commands.size}\r"
|
15
|
+
|
16
|
+
shell_output = IO.popen(command, err: %i[child out], &:read)
|
17
|
+
|
18
|
+
status = $CHILD_STATUS.exitstatus
|
19
|
+
|
20
|
+
unless status.zero?
|
21
|
+
print_progress "\n"
|
22
|
+
print_progress "#{shell_output}\n"
|
23
|
+
raise Error, "process exit with #{status}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
print_progress "\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def print_progress(str)
|
33
|
+
$stderr.print(str) if @show_progress
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module DuoSplitter
|
7
|
+
module Commands
|
8
|
+
class BaseCommand
|
9
|
+
attr_reader :parser, :context
|
10
|
+
|
11
|
+
def initialize(argv)
|
12
|
+
@parser = OptionParser.new
|
13
|
+
@context = Context.new
|
14
|
+
@context.output_dir = default_output_dir if default_output_dir
|
15
|
+
|
16
|
+
parse_options(argv)
|
17
|
+
handle_audio_paths(argv)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
raise Error, '#run must be defined in sub classes'
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def default_output_dir
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def print_done
|
31
|
+
puts 'done.' if context.show_progress
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_output_dir
|
35
|
+
parser.on('-d', '--output-dir=PATH', "Output directory (default: #{context.output_dir.to_s.inspect})") do |path|
|
36
|
+
context.output_dir = Pathname.new(path)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def on_output_format
|
41
|
+
formats = Encoders::BaseEncoder.known_encoders.keys.sort.map(&:to_s)
|
42
|
+
message = %(Output format (default: #{context.output_format.inspect}; one of #{formats.map(&:inspect).join(', ')}))
|
43
|
+
parser.on('-f', '--format=FORMAT', formats, message) do |format|
|
44
|
+
context.output_format = format
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def on_output_intro
|
49
|
+
parser.on('--[no-]output-intro', "Output intro track (default: #{context.output_intro})") do |flag|
|
50
|
+
context.output_intro = flag
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_prefix_section_number
|
55
|
+
parser.on('--[no-]section-number', "Add section number to output file name (default: #{context.prefix_section_number})") do |flag|
|
56
|
+
context.prefix_section_number = flag
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def on_show_progress
|
61
|
+
parser.on('--[no-]progress', "Show progress (default: #{context.show_progress})") do |flag|
|
62
|
+
context.show_progress = flag
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def on_ffmpeg_path
|
67
|
+
parser.on('--ffmpeg-path=PATH', "Path to ffmpeg command (default: #{context.ffmpeg_path.inspect})") do |path|
|
68
|
+
context.ffmpeg_path = path
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def on_sox_path
|
73
|
+
parser.on('--sox-path=PATH', "Path to sox command (default: #{context.sox_path.inspect})") do |path|
|
74
|
+
context.sox_path = path
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def on_use_notification_sound
|
79
|
+
parser.on('--[no-]notification-sound', "Use notification sound (default: #{context.use_notification_sound})") do |flag|
|
80
|
+
context.use_notification_sound = flag
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def on_notification_sound_path
|
85
|
+
parser.on('--notification-sound-path=PATH', "Path to notification sound (default: #{context.notification_sound_path})") do |path|
|
86
|
+
context.notification_sound_path = Pathname.new(path)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse!(argv)
|
91
|
+
parser.order!(argv)
|
92
|
+
rescue OptionParser::ParseError => e
|
93
|
+
raise Error, e.message
|
94
|
+
end
|
95
|
+
|
96
|
+
def after_parse
|
97
|
+
context.output_intro = false unless context.prefix_section_number
|
98
|
+
end
|
99
|
+
|
100
|
+
def handle_audio_paths(argv)
|
101
|
+
raise Error, 'no input files were given' if argv.empty?
|
102
|
+
|
103
|
+
argv.each do |filename|
|
104
|
+
audio_path = Pathname.new(filename)
|
105
|
+
|
106
|
+
match_data = /\A(\d+)/.match(audio_path.basename.to_s)
|
107
|
+
|
108
|
+
raise Error, "input file name doesn't start with a number: #{audio_path.basename}" unless match_data
|
109
|
+
|
110
|
+
section_number = match_data[1].to_i
|
111
|
+
|
112
|
+
section = context.album.sections.find {|s| s.number == section_number }
|
113
|
+
|
114
|
+
raise Error, "invalid section number: #{section_number}" unless section
|
115
|
+
|
116
|
+
section.audio_path = audio_path
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DuoSplitter
|
4
|
+
module Commands
|
5
|
+
class OverlappingCommand < BaseCommand
|
6
|
+
def run
|
7
|
+
Services::CreateOverlappingSentences.new(context: context).run
|
8
|
+
print_done
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def default_output_dir
|
14
|
+
Pathname.new('~/Desktop/DUO 3.0 (Overlapping)').expand_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_options(argv)
|
18
|
+
parser.banner = %(Usage: #{parser.program_name} [options] overlapping "01 Track 01.wav" ... "45 Track 45.wav")
|
19
|
+
|
20
|
+
on_output_dir
|
21
|
+
on_output_format
|
22
|
+
on_output_intro
|
23
|
+
on_prefix_section_number
|
24
|
+
on_show_progress
|
25
|
+
on_ffmpeg_path
|
26
|
+
on_sox_path
|
27
|
+
on_notification_sound_path
|
28
|
+
|
29
|
+
parse!(argv)
|
30
|
+
|
31
|
+
after_parse
|
32
|
+
end
|
33
|
+
|
34
|
+
Runner.register_command(:overlapping, self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|