duo_splitter 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.ja.md +128 -0
  3. data/README.md +13 -11
  4. data/exe/duo_splitter +9 -3
  5. data/lib/duo_splitter.rb +39 -10
  6. data/lib/duo_splitter/batch_processor.rb +36 -0
  7. data/lib/duo_splitter/commands/base_command.rb +121 -0
  8. data/lib/duo_splitter/commands/overlapping_command.rb +37 -0
  9. data/lib/duo_splitter/commands/repeating_command.rb +38 -0
  10. data/lib/duo_splitter/commands/split_command.rb +31 -0
  11. data/lib/duo_splitter/context.rb +34 -0
  12. data/lib/duo_splitter/encoders/aac_encoder.rb +17 -0
  13. data/lib/duo_splitter/encoders/base_encoder.rb +57 -0
  14. data/lib/duo_splitter/encoders/mp3_encoder.rb +17 -0
  15. data/lib/duo_splitter/encoders/wav_encoder.rb +17 -0
  16. data/lib/duo_splitter/models/album.rb +23 -0
  17. data/lib/duo_splitter/models/section.rb +38 -0
  18. data/lib/duo_splitter/models/sentence.rb +35 -0
  19. data/lib/duo_splitter/runner.rb +43 -64
  20. data/lib/duo_splitter/services/create_overlapping_sentences.rb +19 -0
  21. data/lib/duo_splitter/services/create_repeating_sentences.rb +20 -0
  22. data/lib/duo_splitter/services/create_sentences.rb +18 -0
  23. data/lib/duo_splitter/services/support/base_concatenate.rb +46 -0
  24. data/lib/duo_splitter/services/support/create_blank_sentences.rb +40 -0
  25. data/lib/duo_splitter/services/support/encode.rb +23 -0
  26. data/lib/duo_splitter/services/support/overlapping_concatenate.rb +19 -0
  27. data/lib/duo_splitter/services/support/repeating_concatenate.rb +22 -0
  28. data/lib/duo_splitter/services/support/split_tracks.rb +42 -0
  29. data/lib/duo_splitter/temp_dir_wrapper.rb +20 -0
  30. data/lib/duo_splitter/version.rb +3 -1
  31. metadata +34 -15
  32. data/lib/duo_splitter/aac_encoder.rb +0 -13
  33. data/lib/duo_splitter/album.rb +0 -21
  34. data/lib/duo_splitter/encoder.rb +0 -71
  35. data/lib/duo_splitter/mp3_encoder.rb +0 -13
  36. data/lib/duo_splitter/section.rb +0 -30
  37. data/lib/duo_splitter/sentence.rb +0 -22
  38. data/lib/duo_splitter/wav_encoder.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29142faa6db1a28c4729cfa2c84006ec5de9e7f57cf47ad5d14bdd450d05017b
4
- data.tar.gz: e788f6c989a1f852443f130f7c2cff7d2543798f2ae4563ca47964630df95231
3
+ metadata.gz: cc561bd757c37766b2d291595d13e381b663fc762a1e787192ef742e4866f45e
4
+ data.tar.gz: 39e5095aaf66aed68a33208dcac788261abfaba3e40eaefe36513df835121c36
5
5
  SHA512:
6
- metadata.gz: 0a6a9cfa9406970d34f0a746f4ccb776bc3a126cf17e198f37344b76e887bd783c9ec1b57a54433a308e741a97d9a143fbb312b243e6fbfeb7f4556b69b1c0bc
7
- data.tar.gz: 8bcf3160dec0573f8151835fc521176e0e336846a74a8f370e251ef4d9dff6943c4700fed32771d7c4add8466093a56a212ade14417b9c1de8c487f31fe6da30
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
- # `duo_splitter`
1
+ [Read this README in Japanese (日本語で読む)](README.ja.md)
2
2
 
3
- This gem provides a command to split the tracks into each sentences from [DUO 3.0 CD](https://www.amazon.co.jp/dp/4900790079)
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 "duo_splitter"
4
+ require 'duo_splitter'
4
5
 
5
- runner = DuoSplitter::Runner.new(ARGV)
6
- runner.run
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
- require "duo_splitter/album"
2
- require "duo_splitter/section"
3
- require "duo_splitter/sentence"
1
+ # frozen_string_literal: true
4
2
 
5
- require "duo_splitter/encoder"
6
- require "duo_splitter/aac_encoder"
7
- require "duo_splitter/mp3_encoder"
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 "duo_splitter/runner"
7
+ require 'duo_splitter/batch_processor'
11
8
 
12
- require "duo_splitter/version"
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
- DATA_DIR = Pathname.new(__dir__).parent.join('data')
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