Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

録音機能 #1

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

```bash
$ docker-compose up -d
$ docker-compose exec app bundle exec rails db:create
$ docker-compose exec app bundle exec rails db:setup
```
3 changes: 3 additions & 0 deletions app/assets/stylesheets/records.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Place all the styles related to the Records controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
16 changes: 16 additions & 0 deletions app/controllers/records_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class RecordsController < ApplicationController
def index
@records = Record.all
@record = Record.new
end

def create
record_params = params.require(:record).permit(:voice)
@record = Record.new(record_params)
if @record.save
head :created
else
head :unprocessable_entity
end
end
end
2 changes: 2 additions & 0 deletions app/helpers/records_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module RecordsHelper
end
100 changes: 95 additions & 5 deletions app/javascript/packs/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,105 @@
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

require("@rails/ujs").start();
require("turbolinks").start();
require("@rails/activestorage").start();
require("channels");
const OpusMediaRecorder = require("opus-media-recorder");
const Worker = require("opus-media-recorder/encoderWorker.js");
const OggOpusWasm = require("opus-media-recorder/OggOpusEncoder.wasm");
const WebMOpusWasm = require("opus-media-recorder/WebMOpusEncoder.wasm");
const axios = require("axios");

// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

// Polyfill
window.MediaRecorder = OpusMediaRecorder;

document.addEventListener("turbolinks:load", init);

function init() {
if (!navigator.mediaDevices.getUserMedia) return;

const soundClips = document.querySelector("#js-sound-clips");
const startButton = document.querySelector("#js-start-recording");
const stopButton = document.querySelector("#js-stop-recording");

startButton.disabled = false;
stopButton.disabled = true;

const constraints = { audio: true };
let chunks = [];

// iOS Safari は ogg の再生ができない
// このサンプルでは容量が大きくなってもやむなしとして wav で
const mimeType = "audio/wav";

const onSuccess = stream => {
const options = {
mimeType: mimeType
};
const workerOptions = {
encoderWorkerFactory: _ => new Worker(),
OggOpusEncoderWasmPath: OggOpusWasm,
WebMOpusEncoderWasmPath: WebMOpusWasm
};
const mediaRecorder = new MediaRecorder(stream, options, workerOptions);

startButton.addEventListener("click", () => {
mediaRecorder.start();
console.log(mediaRecorder.state);
console.log("recorder started");
startButton.disabled = true;
stopButton.disabled = false;
});

stopButton.addEventListener("click", () => {
mediaRecorder.stop();
console.log(mediaRecorder.state);
console.log("recorder stopped");
startButton.disabled = false;
stopButton.disabled = true;
});

mediaRecorder.onstop = e => {
console.log("data available after MediaRecorder.stop() called.");

var blob = new Blob(chunks, { type: mimeType });
chunks = [];

var uploadFormData = new FormData();
var csrfParam = document.querySelector("meta[name='csrf-param']").content;
var csrfToken = document.querySelector("meta[name='csrf-token']").content;
uploadFormData.append(csrfParam, csrfToken);
uploadFormData.append("record[voice]", blob);

axios
.post("/records", uploadFormData)
.then(result => {
console.log(result);
window.location.reload(true);
})
.catch(error => {
console.log(error);
});

console.log("recorder stopped");
};

mediaRecorder.ondataavailable = e => {
chunks.push(e.data);
};
};

var onError = err => {
console.log("The following error occured: " + err);
};

navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
}
3 changes: 3 additions & 0 deletions app/models/record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Record < ApplicationRecord
has_one_attached :voice
end
14 changes: 14 additions & 0 deletions app/views/records/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<h1>Records#index</h1>
<p>Find me in app/views/records/index.html.erb</p>

<div>
<button id="js-start-recording">Start</button>
<button id="js-stop-recording">Stop</button>
</div>

<% @records.each do |record| %>
<article>
<p><%= record.created_at %></p>
<%= audio_tag rails_blob_url(record.voice, disposition: "attachment"), controls: true %>
</article>
<% end %>
3 changes: 3 additions & 0 deletions config/initializers/mime_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf

# public assets
Rack::Mime::MIME_TYPES[".wasm"] = "application/wasm"
3 changes: 2 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
root "records#index"
resources :records
end
23 changes: 21 additions & 2 deletions config/webpack/environment.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
const { environment } = require('@rails/webpacker')
const { environment } = require("@rails/webpacker");

module.exports = environment
const opusMediaRecorderEncoderWorkerLoader = {
test: /opus-media-recorder\/encoderWorker\.js$/,
loader: "worker-loader"
};
const opusMediaRecorderWasmLoader = {
test: /opus-media-recorder\/.*\.wasm$/,
type: "javascript/auto",
loader: "file-loader"
};

environment.loaders.prepend(
"opusMediaRecorderEncoderWorkerLoader",
opusMediaRecorderEncoderWorkerLoader
);
environment.loaders.prepend(
"opusMediaRecorderWasmLoader",
opusMediaRecorderWasmLoader
);

module.exports = environment;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
def change
create_table :active_storage_blobs do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.bigint :byte_size, null: false
t.string :checksum, null: false
t.datetime :created_at, null: false

t.index [ :key ], unique: true
end

create_table :active_storage_attachments do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false
t.references :blob, null: false

t.datetime :created_at, null: false

t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
end
8 changes: 8 additions & 0 deletions db/migrate/20190703130233_create_records.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CreateRecords < ActiveRecord::Migration[6.0]
def change
create_table :records do |t|

t.timestamps
end
end
end
45 changes: 45 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `rails
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2019_07_03_130233) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end

create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum", null: false
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end

create_table "records", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end

add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
end
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
"@rails/activestorage": "^6.0.0-alpha",
"@rails/ujs": "^6.0.0-alpha",
"@rails/webpacker": "^4.0.7",
"axios": "^0.19.0",
"turbolinks": "^5.2.0"
},
"version": "0.1.0",
"devDependencies": {
"webpack-dev-server": "^3.7.2"
"opus-media-recorder": "^0.7.19",
"webpack-dev-server": "^3.7.2",
"worker-loader": "^2.0.0"
}
}
12 changes: 12 additions & 0 deletions spec/controllers/records_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'rails_helper'

RSpec.describe RecordsController, type: :controller do

describe "GET #index" do
it "returns http success" do
get :index
expect(response).to have_http_status(:success)
end
end

end
15 changes: 15 additions & 0 deletions spec/helpers/records_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'rails_helper'

# Specs in this file have access to a helper object that includes
# the RecordsHelper. For example:
#
# describe RecordsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe RecordsHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
5 changes: 5 additions & 0 deletions spec/models/record_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe Record, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
5 changes: 5 additions & 0 deletions spec/views/records/index.html.erb_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe "records/index.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading