soiz1 commited on
Commit
f930612
·
1 Parent(s): 59c8ec2

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +107 -67
index.html CHANGED
@@ -47,6 +47,7 @@
47
  border-radius: 5px;
48
  background-color: #000;
49
  display: block;
 
50
  }
51
 
52
  .video-controls {
@@ -252,6 +253,37 @@
252
  color: #ccd6f6;
253
  }
254
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  input[type="number"], input[type="checkbox"], select {
256
  background-color: #112240;
257
  border: 1px solid #64ffda;
@@ -260,12 +292,6 @@
260
  border-radius: 3px;
261
  }
262
 
263
- .buttons {
264
- display: flex;
265
- gap: 10px;
266
- justify-content: center;
267
- }
268
-
269
  .tech-decoration {
270
  width: 100%;
271
  height: 2px;
@@ -316,8 +342,8 @@
316
  <input type="range" class="volume-slider" id="volume-slider" min="0" max="1" step="0.01" value="1">
317
  </div>
318
  <div class="speed-control">
319
- <span class="speed-value" id="speed-value">1x</span>
320
- <input type="range" class="speed-slider" id="speed-slider" min="0.25" max="3" step="0.25" value="1">
321
  </div>
322
  <button class="control-button fullscreen-button" id="fullscreen-btn">⛶</button>
323
  </div>
@@ -341,14 +367,18 @@
341
  <input type="checkbox" id="loop">
342
  </div>
343
  <div class="setting-item">
344
- <label for="global-volume">全体音量係数:</label>
345
- <input type="range" id="global-volume" min="0" max="3" step="0.1" value="1">
346
- <span id="global-volume-value">1</span>
 
 
347
  </div>
348
  <div class="setting-item">
349
- <label for="settings-speed">再生速度:</label>
350
- <input type="range" id="settings-speed" min="0.25" max="3" step="0.25" value="1">
351
- <span id="settings-speed-value">1x</span>
 
 
352
  </div>
353
  </div>
354
 
@@ -359,37 +389,29 @@
359
  <div class="audio-item">
360
  <label>p.mp3</label>
361
  <input type="range" class="audio-slider" data-audio="p" min="0" max="1" step="0.01" value="1">
362
- <span class="volume-value">1</span>
363
  </div>
364
  <div class="audio-item">
365
  <label>a.mp3</label>
366
  <input type="range" class="audio-slider" data-audio="a" min="0" max="1" step="0.01" value="1">
367
- <span class="volume-value">1</span>
368
  </div>
369
  <div class="audio-item">
370
  <label>t.mp3</label>
371
  <input type="range" class="audio-slider" data-audio="t" min="0" max="1" step="0.01" value="1">
372
- <span class="volume-value">1</span>
373
  </div>
374
  <div class="audio-item">
375
  <label>s.mp3</label>
376
  <input type="range" class="audio-slider" data-audio="s" min="0" max="1" step="0.01" value="1">
377
- <span class="volume-value">1</span>
378
  </div>
379
  <div class="audio-item">
380
  <label>k.mp3</label>
381
  <input type="range" class="audio-slider" data-audio="k" min="0" max="1" step="0.01" value="1">
382
- <span class="volume-value">1</span>
383
  </div>
384
  </div>
385
-
386
- <div class="tech-decoration"></div>
387
-
388
- <div class="buttons">
389
- <button id="play-btn">再生</button>
390
- <button id="pause-btn">一時停止</button>
391
- <button id="stop-btn">停止</button>
392
- </div>
393
  </div>
394
 
395
  <script>
@@ -406,12 +428,9 @@
406
  const volumeSlider = document.getElementById('volume-slider');
407
  const speedSlider = document.getElementById('speed-slider');
408
  const speedValue = document.getElementById('speed-value');
409
- const settingsSpeedSlider = document.getElementById('settings-speed');
410
- const settingsSpeedValue = document.getElementById('settings-speed-value');
411
  const fullscreenBtn = document.getElementById('fullscreen-btn');
412
- const playBtn = document.getElementById('play-btn');
413
- const pauseBtn = document.getElementById('pause-btn');
414
- const stopBtn = document.getElementById('stop-btn');
415
  const startTimeInput = document.getElementById('start-time');
416
  const endTimeInput = document.getElementById('end-time');
417
  const loopCheckbox = document.getElementById('loop');
@@ -425,6 +444,7 @@
425
  const audioBuffers = {};
426
  const audioSources = {};
427
  const gainNodes = {};
 
428
 
429
  // 音声ファイル名の配列
430
  const audioFiles = ['p', 'a', 't', 's', 'k'];
@@ -434,6 +454,7 @@
434
  let isPlaying = false;
435
  let isVideoPlaying = false;
436
  let lastVolume = 1;
 
437
 
438
  // 動画のメタデータが読み込まれたら
439
  video.addEventListener('loadedmetadata', function() {
@@ -466,6 +487,16 @@
466
  // 動画の時間更新イベント
467
  video.addEventListener('timeupdate', updateTimeDisplay);
468
 
 
 
 
 
 
 
 
 
 
 
469
  // プログレスバークリックでシーク
470
  progressContainer.addEventListener('click', function(e) {
471
  if (!video.duration) return;
@@ -474,16 +505,30 @@
474
  const pos = (e.clientX - rect.left) / rect.width;
475
  const seekTime = pos * video.duration;
476
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  video.currentTime = seekTime;
478
 
479
  // 音声も同期
480
  audioFiles.forEach(file => {
481
  if (audioSources[file]) {
482
  audioSources[file].stop();
483
- playAudio(file, seekTime);
 
 
484
  }
485
  });
486
- });
487
 
488
  // プログレスバー上でマウス移動時に時間を表示
489
  progressContainer.addEventListener('mousemove', function(e) {
@@ -505,6 +550,15 @@
505
  progressTime.style.display = 'none';
506
  });
507
 
 
 
 
 
 
 
 
 
 
508
  // 再生/一時停止ボタン
509
  playPauseBtn.addEventListener('click', function() {
510
  if (isVideoPlaying) {
@@ -548,24 +602,26 @@
548
  // 再生速度スライダー (動画プレイヤー)
549
  speedSlider.addEventListener('input', function() {
550
  const speed = parseFloat(this.value);
551
- speedValue.textContent = `${speed}x`;
 
 
552
  updatePlaybackRate(speed);
553
  });
554
 
555
  // 再生速度スライダー (設定メニュー)
556
- settingsSpeedSlider.addEventListener('input', function() {
557
  const speed = parseFloat(this.value);
558
- settingsSpeedValue.textContent = `${speed}x`;
559
  speedSlider.value = speed;
560
- speedValue.textContent = `${speed}x`;
561
  updatePlaybackRate(speed);
562
  });
563
 
564
- // 再生速度を更新
565
  function updatePlaybackRate(speed) {
566
  video.playbackRate = speed;
567
 
568
- // 音声の再生速度も更新
569
  audioFiles.forEach(file => {
570
  if (audioSources[file]) {
571
  audioSources[file].playbackRate.value = speed;
@@ -596,7 +652,7 @@
596
  video.controls = false;
597
  } else {
598
  // 通常表示時の処理
599
- video.controls = false; // ブラウザのコントロールは非表示のまま
600
  }
601
  }
602
 
@@ -639,7 +695,11 @@
639
  const endTime = parseFloat(endTimeInput.value) || duration;
640
  const loop = loopCheckbox.checked;
641
 
642
- source.start(0, currentTime, endTime - currentTime);
 
 
 
 
643
 
644
  // ループ設定
645
  source.loop = loop;
@@ -649,7 +709,7 @@
649
  source.loopEnd = endTime;
650
  }
651
 
652
- // 再生速度を同期
653
  source.playbackRate.value = video.playbackRate;
654
 
655
  audioSources[file] = source;
@@ -657,8 +717,9 @@
657
 
658
  // 再生関数
659
  function playMedia() {
660
- const startTime = parseFloat(startTimeInput.value) || 0;
661
  let endTime = parseFloat(endTimeInput.value) || videoDuration;
 
662
 
663
  // 終了時間が動画の長さを超えないように
664
  endTime = Math.min(endTime, videoDuration);
@@ -683,23 +744,6 @@
683
  isPlaying = true;
684
  isVideoPlaying = true;
685
  playPauseBtn.textContent = '⏸';
686
-
687
- // 終了時間に達したら停止
688
- video.ontimeupdate = function() {
689
- if (video.currentTime >= endTime) {
690
- if (!loopCheckbox.checked) {
691
- stopMedia();
692
- } else {
693
- video.currentTime = startTime;
694
- audioFiles.forEach(file => {
695
- if (audioSources[file]) {
696
- audioSources[file].stop();
697
- playAudio(file, startTime);
698
- }
699
- });
700
- }
701
- }
702
- };
703
  }
704
 
705
  // 一時停止関数
@@ -717,6 +761,7 @@
717
  isPlaying = false;
718
  isVideoPlaying = false;
719
  playPauseBtn.textContent = '▶';
 
720
  }
721
 
722
  // 停止関数
@@ -727,11 +772,6 @@
727
  updateTimeDisplay();
728
  }
729
 
730
- // イベントリスナーを設定
731
- playBtn.addEventListener('click', playMedia);
732
- pauseBtn.addEventListener('click', pauseMedia);
733
- stopBtn.addEventListener('click', stopMedia);
734
-
735
  // ボリュームスライダーのイベント
736
  audioSliders.forEach((slider, index) => {
737
  slider.addEventListener('input', function() {
@@ -765,7 +805,7 @@
765
  loadAudioFiles();
766
  updateVolumeIcon();
767
  volumeSlider.value = video.volume;
768
- video.controls = false; // ブラウザのコントロールを非表示
769
  });
770
  </script>
771
  </body>
 
47
  border-radius: 5px;
48
  background-color: #000;
49
  display: block;
50
+ cursor: pointer;
51
  }
52
 
53
  .video-controls {
 
253
  color: #ccd6f6;
254
  }
255
 
256
+ .global-volume-container, .playback-speed-container {
257
+ display: flex;
258
+ align-items: center;
259
+ gap: 10px;
260
+ width: 100%;
261
+ }
262
+
263
+ .global-volume-slider, .playback-speed-slider {
264
+ flex-grow: 1;
265
+ height: 8px;
266
+ -webkit-appearance: none;
267
+ background: #1e2a47;
268
+ border-radius: 5px;
269
+ outline: none;
270
+ }
271
+
272
+ .global-volume-slider::-webkit-slider-thumb,
273
+ .playback-speed-slider::-webkit-slider-thumb {
274
+ -webkit-appearance: none;
275
+ width: 16px;
276
+ height: 16px;
277
+ background: #64ffda;
278
+ border-radius: 50%;
279
+ cursor: pointer;
280
+ }
281
+
282
+ .slider-value {
283
+ min-width: 40px;
284
+ text-align: right;
285
+ }
286
+
287
  input[type="number"], input[type="checkbox"], select {
288
  background-color: #112240;
289
  border: 1px solid #64ffda;
 
292
  border-radius: 3px;
293
  }
294
 
 
 
 
 
 
 
295
  .tech-decoration {
296
  width: 100%;
297
  height: 2px;
 
342
  <input type="range" class="volume-slider" id="volume-slider" min="0" max="1" step="0.01" value="1">
343
  </div>
344
  <div class="speed-control">
345
+ <span class="speed-value" id="speed-value">1.00x</span>
346
+ <input type="range" class="speed-slider" id="speed-slider" min="0.25" max="3" step="0.05" value="1">
347
  </div>
348
  <button class="control-button fullscreen-button" id="fullscreen-btn">⛶</button>
349
  </div>
 
367
  <input type="checkbox" id="loop">
368
  </div>
369
  <div class="setting-item">
370
+ <div class="global-volume-container">
371
+ <label>全体音量係数:</label>
372
+ <input type="range" class="global-volume-slider" id="global-volume" min="0" max="3" step="0.1" value="1">
373
+ <span class="slider-value" id="global-volume-value">1.0</span>
374
+ </div>
375
  </div>
376
  <div class="setting-item">
377
+ <div class="playback-speed-container">
378
+ <label>再生速度:</label>
379
+ <input type="range" class="playback-speed-slider" id="playback-speed" min="0.25" max="3" step="0.05" value="1">
380
+ <span class="slider-value" id="playback-speed-value">1.00x</span>
381
+ </div>
382
  </div>
383
  </div>
384
 
 
389
  <div class="audio-item">
390
  <label>p.mp3</label>
391
  <input type="range" class="audio-slider" data-audio="p" min="0" max="1" step="0.01" value="1">
392
+ <span class="slider-value volume-value">1.00</span>
393
  </div>
394
  <div class="audio-item">
395
  <label>a.mp3</label>
396
  <input type="range" class="audio-slider" data-audio="a" min="0" max="1" step="0.01" value="1">
397
+ <span class="slider-value volume-value">1.00</span>
398
  </div>
399
  <div class="audio-item">
400
  <label>t.mp3</label>
401
  <input type="range" class="audio-slider" data-audio="t" min="0" max="1" step="0.01" value="1">
402
+ <span class="slider-value volume-value">1.00</span>
403
  </div>
404
  <div class="audio-item">
405
  <label>s.mp3</label>
406
  <input type="range" class="audio-slider" data-audio="s" min="0" max="1" step="0.01" value="1">
407
+ <span class="slider-value volume-value">1.00</span>
408
  </div>
409
  <div class="audio-item">
410
  <label>k.mp3</label>
411
  <input type="range" class="audio-slider" data-audio="k" min="0" max="1" step="0.01" value="1">
412
+ <span class="slider-value volume-value">1.00</span>
413
  </div>
414
  </div>
 
 
 
 
 
 
 
 
415
  </div>
416
 
417
  <script>
 
428
  const volumeSlider = document.getElementById('volume-slider');
429
  const speedSlider = document.getElementById('speed-slider');
430
  const speedValue = document.getElementById('speed-value');
431
+ const playbackSpeedSlider = document.getElementById('playback-speed');
432
+ const playbackSpeedValue = document.getElementById('playback-speed-value');
433
  const fullscreenBtn = document.getElementById('fullscreen-btn');
 
 
 
434
  const startTimeInput = document.getElementById('start-time');
435
  const endTimeInput = document.getElementById('end-time');
436
  const loopCheckbox = document.getElementById('loop');
 
444
  const audioBuffers = {};
445
  const audioSources = {};
446
  const gainNodes = {};
447
+ const pitchShiftNodes = {};
448
 
449
  // 音声ファイル名の配列
450
  const audioFiles = ['p', 'a', 't', 's', 'k'];
 
454
  let isPlaying = false;
455
  let isVideoPlaying = false;
456
  let lastVolume = 1;
457
+ let shouldPlayFromStartTime = false;
458
 
459
  // 動画のメタデータが読み込まれたら
460
  video.addEventListener('loadedmetadata', function() {
 
487
  // 動画の時間更新イベント
488
  video.addEventListener('timeupdate', updateTimeDisplay);
489
 
490
+ // 動画終了時の処理
491
+ video.addEventListener('ended', function() {
492
+ const startTime = parseFloat(startTimeInput.value) || 0;
493
+ if (!loopCheckbox.checked) {
494
+ stopMedia();
495
+ video.currentTime = startTime;
496
+ updateTimeDisplay();
497
+ }
498
+ });
499
+
500
  // プログレスバークリックでシーク
501
  progressContainer.addEventListener('click', function(e) {
502
  if (!video.duration) return;
 
505
  const pos = (e.clientX - rect.left) / rect.width;
506
  const seekTime = pos * video.duration;
507
 
508
+ seekMedia(seekTime);
509
+ });
510
+
511
+ // 指定した時間にシーク
512
+ function seekMedia(time) {
513
+ const duration = video.duration || videoDuration;
514
+ const startTime = parseFloat(startTimeInput.value) || 0;
515
+ const endTime = parseFloat(endTimeInput.value) || duration;
516
+
517
+ // 範囲内に制限
518
+ const seekTime = Math.max(startTime, Math.min(time, endTime));
519
+
520
  video.currentTime = seekTime;
521
 
522
  // 音声も同期
523
  audioFiles.forEach(file => {
524
  if (audioSources[file]) {
525
  audioSources[file].stop();
526
+ if (isPlaying) {
527
+ playAudio(file, seekTime);
528
+ }
529
  }
530
  });
531
+ }
532
 
533
  // プログレスバー上でマウス移動時に時間を表示
534
  progressContainer.addEventListener('mousemove', function(e) {
 
550
  progressTime.style.display = 'none';
551
  });
552
 
553
+ // 動画クリックで再生/一時停止
554
+ video.addEventListener('click', function() {
555
+ if (isVideoPlaying) {
556
+ pauseMedia();
557
+ } else {
558
+ playMedia();
559
+ }
560
+ });
561
+
562
  // 再生/一時停止ボタン
563
  playPauseBtn.addEventListener('click', function() {
564
  if (isVideoPlaying) {
 
602
  // 再生速度スライダー (動画プレイヤー)
603
  speedSlider.addEventListener('input', function() {
604
  const speed = parseFloat(this.value);
605
+ speedValue.textContent = speed.toFixed(2) + 'x';
606
+ playbackSpeedSlider.value = speed;
607
+ playbackSpeedValue.textContent = speed.toFixed(2) + 'x';
608
  updatePlaybackRate(speed);
609
  });
610
 
611
  // 再生速度スライダー (設定メニュー)
612
+ playbackSpeedSlider.addEventListener('input', function() {
613
  const speed = parseFloat(this.value);
614
+ playbackSpeedValue.textContent = speed.toFixed(2) + 'x';
615
  speedSlider.value = speed;
616
+ speedValue.textContent = speed.toFixed(2) + 'x';
617
  updatePlaybackRate(speed);
618
  });
619
 
620
+ // 再生速度を更新 (音の高さを維持)
621
  function updatePlaybackRate(speed) {
622
  video.playbackRate = speed;
623
 
624
+ // 音声の再生速度も更新 (音の高さは維持)
625
  audioFiles.forEach(file => {
626
  if (audioSources[file]) {
627
  audioSources[file].playbackRate.value = speed;
 
652
  video.controls = false;
653
  } else {
654
  // 通常表示時の処理
655
+ video.controls = false;
656
  }
657
  }
658
 
 
695
  const endTime = parseFloat(endTimeInput.value) || duration;
696
  const loop = loopCheckbox.checked;
697
 
698
+ // 再生範囲を計算
699
+ const playStartTime = Math.max(startTime, parseFloat(startTimeInput.value) || 0);
700
+ const playDuration = Math.min(endTime, duration) - playStartTime;
701
+
702
+ source.start(0, playStartTime, playDuration);
703
 
704
  // ループ設定
705
  source.loop = loop;
 
709
  source.loopEnd = endTime;
710
  }
711
 
712
+ // 再生速度を同期 (音の高さは維持)
713
  source.playbackRate.value = video.playbackRate;
714
 
715
  audioSources[file] = source;
 
717
 
718
  // 再生関数
719
  function playMedia() {
720
+ const startTime = shouldPlayFromStartTime ? (parseFloat(startTimeInput.value) || 0) : video.currentTime;
721
  let endTime = parseFloat(endTimeInput.value) || videoDuration;
722
+ shouldPlayFromStartTime = false;
723
 
724
  // 終了時間が動画の長さを超えないように
725
  endTime = Math.min(endTime, videoDuration);
 
744
  isPlaying = true;
745
  isVideoPlaying = true;
746
  playPauseBtn.textContent = '⏸';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  }
748
 
749
  // 一時停止関数
 
761
  isPlaying = false;
762
  isVideoPlaying = false;
763
  playPauseBtn.textContent = '▶';
764
+ shouldPlayFromStartTime = true;
765
  }
766
 
767
  // 停止関数
 
772
  updateTimeDisplay();
773
  }
774
 
 
 
 
 
 
775
  // ボリュームスライダーのイベント
776
  audioSliders.forEach((slider, index) => {
777
  slider.addEventListener('input', function() {
 
805
  loadAudioFiles();
806
  updateVolumeIcon();
807
  volumeSlider.value = video.volume;
808
+ video.controls = false;
809
  });
810
  </script>
811
  </body>