soiz1 commited on
Commit
c4efc4e
·
1 Parent(s): 4b2320d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +287 -50
index.html CHANGED
@@ -319,9 +319,134 @@
319
  width: 100%;
320
  border-radius: 0;
321
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  </style>
323
  </head>
324
  <body>
 
 
 
 
 
 
 
 
 
 
 
 
325
  <h1>高度な音声動画プレイヤー</h1>
326
 
327
  <div class="container">
@@ -336,7 +461,7 @@
336
  </div>
337
  <div class="main-controls">
338
  <button class="control-button" id="play-pause-btn">▶</button>
339
- <div class="time-display" id="time-display">00:00 / 00:00</div>
340
  <div class="volume-control">
341
  <button class="volume-button" id="volume-btn">🔊</button>
342
  <input type="range" class="volume-slider" id="volume-slider" min="0" max="1" step="0.01" value="1">
@@ -356,11 +481,17 @@
356
  <h2>設定</h2>
357
  <div class="setting-item">
358
  <label for="start-time">再生開始秒数:</label>
359
- <input type="number" id="start-time" min="0" value="0" step="0.1">
 
 
 
360
  </div>
361
  <div class="setting-item">
362
  <label for="end-time">再生終了秒数:</label>
363
- <input type="number" id="end-time" min="0" value="0" step="0.1">
 
 
 
364
  </div>
365
  <div class="setting-item">
366
  <label for="loop">ループ再生:</label>
@@ -433,14 +564,19 @@
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');
437
  const globalVolumeSlider = document.getElementById('global-volume');
438
  const globalVolumeValue = document.getElementById('global-volume-value');
439
  const audioSliders = document.querySelectorAll('.audio-slider');
440
  const volumeValues = document.querySelectorAll('.volume-value');
 
441
 
442
  // 音声オブジェクトを作成
443
  const audioElements = {};
 
 
444
 
445
  // 音声ファイル名の配列
446
  const audioFiles = ['p', 'a', 't', 's', 'k'];
@@ -451,6 +587,23 @@
451
  let isVideoPlaying = false;
452
  let lastVolume = 1;
453
  let currentPlaybackRate = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
454
 
455
  // 動画のメタデータが読み込まれたら
456
  video.addEventListener('loadedmetadata', function() {
@@ -459,48 +612,61 @@
459
  endTimeInput.max = videoDuration;
460
  startTimeInput.max = videoDuration - 0.1;
461
  updateTimeDisplay();
 
 
462
  });
463
 
464
- document.getElementById('play-pause-btn').addEventListener('click', function() {
465
- // 音声要素の再生を許可
466
- audioFiles.forEach(file => {
467
- if (audioElements[file]) {
468
- audioElements[file].play().catch(e => console.log("Audio play failed:", e));
469
- }
470
- });
 
 
 
 
471
  });
472
 
473
- // 時間表示を更新
474
  function updateTimeDisplay() {
475
  const currentTime = video.currentTime;
476
  const duration = video.duration || videoDuration;
477
 
478
  const currentMinutes = Math.floor(currentTime / 60);
479
  const currentSeconds = Math.floor(currentTime % 60);
 
480
  const durationMinutes = Math.floor(duration / 60);
481
  const durationSeconds = Math.floor(duration % 60);
 
482
 
483
  timeDisplay.textContent =
484
- `${String(currentMinutes).padStart(2, '0')}:${String(currentSeconds).padStart(2, '0')} / ` +
485
- `${String(durationMinutes).padStart(2, '0')}:${String(durationSeconds).padStart(2, '0')}`;
486
 
487
  // プログレスバーを更新
488
  const progressPercent = (currentTime / duration) * 100;
489
  progressBar.style.width = `${progressPercent}%`;
490
- }
491
-
492
- // 動画の時間更新イベント
493
- video.addEventListener('timeupdate', function() {
494
- updateTimeDisplay();
495
 
496
- // ループ再生の場合、終了時間をチェック
497
- if (loopCheckbox.checked) {
498
- const endTime = parseFloat(endTimeInput.value) || videoDuration;
499
- if (video.currentTime >= endTime) {
500
  const startTime = parseFloat(startTimeInput.value) || 0;
501
  seekMedia(startTime);
 
 
 
 
 
502
  }
503
  }
 
 
 
 
 
504
  });
505
 
506
  // 動画終了時の処理
@@ -552,8 +718,9 @@
552
 
553
  const minutes = Math.floor(hoverTime / 60);
554
  const seconds = Math.floor(hoverTime % 60);
 
555
 
556
- progressTime.textContent = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
557
  progressTime.style.display = 'block';
558
  progressTime.style.left = `${pos * 100}%`;
559
  });
@@ -567,12 +734,6 @@
567
  togglePlayPause();
568
  });
569
 
570
- // 再生/一時停止ボタン
571
- playPauseBtn.addEventListener('click', function(e) {
572
- e.stopPropagation(); // 動画クリックとのバブリングを防止
573
- togglePlayPause();
574
- });
575
-
576
  // 再生/一時停止をトグル
577
  function togglePlayPause() {
578
  if (isVideoPlaying) {
@@ -673,6 +834,8 @@
673
 
674
  // 音声ファイルをロード
675
  function loadAudioFiles() {
 
 
676
  audioFiles.forEach(file => {
677
  const audio = new Audio(`${file}.mp3`);
678
  audio.preload = 'auto';
@@ -680,14 +843,41 @@
680
  audio.loop = false;
681
  audioElements[file] = audio;
682
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
683
  // 音声が読み込まれたら
684
  audio.addEventListener('loadedmetadata', function() {
685
  console.log(`${file}.mp3 loaded`);
 
 
 
 
 
 
686
  });
687
 
688
  // エラー処理
689
  audio.addEventListener('error', function() {
690
  console.error(`Error loading ${file}.mp3`);
 
 
 
 
 
 
691
  });
692
  });
693
  }
@@ -701,8 +891,12 @@
701
 
702
  // ボリューム設定
703
  const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
704
- const volume = parseFloat(volumeSlider.value) * parseFloat(globalVolumeSlider.value / 10);
705
- audio.volume = volume;
 
 
 
 
706
 
707
  // 再生速度設定
708
  audio.playbackRate = currentPlaybackRate;
@@ -715,7 +909,16 @@
715
  audio.currentTime = playStartTime;
716
 
717
  // 再生
718
- audio.play().catch(e => console.log("Audio play failed:", e));
 
 
 
 
 
 
 
 
 
719
 
720
  // ループ設定
721
  audio.loop = loopCheckbox.checked;
@@ -732,26 +935,28 @@
732
 
733
  // 再生関数
734
  function playMedia() {
735
- const startTime = video.currentTime;
736
- const endTime = parseFloat(endTimeInput.value) || videoDuration;
737
-
738
- // 終了時間が動画の長さを超えないように
739
- const actualEndTime = Math.min(endTime, videoDuration);
740
 
741
  // 現在位置が終了時間を超えている場合、開始位置に戻る
742
- if (startTime >= actualEndTime) {
743
- video.currentTime = parseFloat(startTimeInput.value) || 0;
 
744
  }
745
 
746
  // 動画を再生
747
- video.play();
748
- isPlaying = true;
749
- isVideoPlaying = true;
750
- playPauseBtn.textContent = '⏸';
751
-
752
- // 音声を再生
753
- audioFiles.forEach(file => {
754
- playAudio(file, video.currentTime);
 
 
 
755
  });
756
  }
757
 
@@ -778,8 +983,12 @@
778
  volumeValues[index].textContent = value.toFixed(2);
779
 
780
  if (audioElements[this.dataset.audio]) {
781
- const globalVolume = parseFloat(globalVolumeSlider.value / 10);
782
- audioElements[this.dataset.audio].volume = value * globalVolume;
 
 
 
 
783
  }
784
  });
785
  });
@@ -793,7 +1002,11 @@
793
  if (audioElements[file]) {
794
  const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
795
  const volume = parseFloat(volumeSlider.value) * value;
796
- audioElements[file].volume = volume;
 
 
 
 
797
  }
798
  });
799
  });
@@ -807,11 +1020,35 @@
807
  });
808
  });
809
 
 
 
 
 
 
 
 
 
 
 
810
  // 初期化
811
  loadAudioFiles();
812
  updateVolumeIcon();
813
  volumeSlider.value = video.volume;
814
  video.controls = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
  });
816
  </script>
817
  </body>
 
319
  width: 100%;
320
  border-radius: 0;
321
  }
322
+
323
+ .time-input-container {
324
+ display: flex;
325
+ align-items: center;
326
+ gap: 5px;
327
+ }
328
+
329
+ .set-time-btn {
330
+ background-color: #112240;
331
+ border: 1px solid #64ffda;
332
+ color: #e6f1ff;
333
+ padding: 5px 8px;
334
+ border-radius: 3px;
335
+ cursor: pointer;
336
+ font-size: 12px;
337
+ transition: background-color 0.3s;
338
+ }
339
+
340
+ .set-time-btn:hover {
341
+ background-color: rgba(100, 255, 218, 0.2);
342
+ }
343
+
344
+ /* ローディングアニメーション */
345
+ .loading-overlay {
346
+ position: fixed;
347
+ top: 0;
348
+ left: 0;
349
+ width: 100%;
350
+ height: 100%;
351
+ background-color: rgba(0, 0, 0, 0.8);
352
+ display: flex;
353
+ justify-content: center;
354
+ align-items: center;
355
+ z-index: 9999;
356
+ transition: opacity 1s ease-out;
357
+ }
358
+
359
+ .spinner-box {
360
+ width: 300px;
361
+ height: 300px;
362
+ display: flex;
363
+ justify-content: center;
364
+ align-items: center;
365
+ background-color: transparent;
366
+ }
367
+
368
+ /* 軌道スタイル */
369
+ .leo {
370
+ position: absolute;
371
+ display: flex;
372
+ justify-content: center;
373
+ align-items: center;
374
+ border-radius: 50%;
375
+ }
376
+
377
+ .blue-orbit {
378
+ width: 165px;
379
+ height: 165px;
380
+ border: 1px solid #91daffa5;
381
+ animation: spin3D 3s linear .2s infinite;
382
+ }
383
+
384
+ .green-orbit {
385
+ width: 120px;
386
+ height: 120px;
387
+ border: 1px solid #91ffbfa5;
388
+ animation: spin3D 2s linear 0s infinite;
389
+ }
390
+
391
+ .red-orbit {
392
+ width: 90px;
393
+ height: 90px;
394
+ border: 1px solid #ffca91a5;
395
+ animation: spin3D 1s linear 0s infinite;
396
+ }
397
+
398
+ .white-orbit {
399
+ width: 60px;
400
+ height: 60px;
401
+ border: 2px solid #ffffff;
402
+ animation: spin3D 10s linear 0s infinite;
403
+ }
404
+
405
+ .w1 {
406
+ transform: rotate3D(1, 1, 1, 90deg);
407
+ }
408
+
409
+ .w2 {
410
+ transform: rotate3D(1, 2, .5, 90deg);
411
+ }
412
+
413
+ .w3 {
414
+ transform: rotate3D(.5, 1, 2, 90deg);
415
+ }
416
+
417
+ /* キーフレームアニメーション */
418
+ @keyframes spin3D {
419
+ from {
420
+ transform: rotate3d(.5,.5,.5, 360deg);
421
+ }
422
+ to {
423
+ transform: rotate3d(0,0,0, 0deg);
424
+ }
425
+ }
426
+
427
+ @keyframes spin {
428
+ from {
429
+ transform: rotate(0deg);
430
+ }
431
+ to {
432
+ transform: rotate(360deg);
433
+ }
434
+ }
435
  </style>
436
  </head>
437
  <body>
438
+ <!-- ローディングオーバーレイ -->
439
+ <div class="loading-overlay" id="loadingOverlay">
440
+ <div class="spinner-box">
441
+ <div class="blue-orbit leo"></div>
442
+ <div class="green-orbit leo"></div>
443
+ <div class="red-orbit leo"></div>
444
+ <div class="white-orbit w1 leo"></div>
445
+ <div class="white-orbit w2 leo"></div>
446
+ <div class="white-orbit w3 leo"></div>
447
+ </div>
448
+ </div>
449
+
450
  <h1>高度な音声動画プレイヤー</h1>
451
 
452
  <div class="container">
 
461
  </div>
462
  <div class="main-controls">
463
  <button class="control-button" id="play-pause-btn">▶</button>
464
+ <div class="time-display" id="time-display">00:00.00 / 00:00.00</div>
465
  <div class="volume-control">
466
  <button class="volume-button" id="volume-btn">🔊</button>
467
  <input type="range" class="volume-slider" id="volume-slider" min="0" max="1" step="0.01" value="1">
 
481
  <h2>設定</h2>
482
  <div class="setting-item">
483
  <label for="start-time">再生開始秒数:</label>
484
+ <div class="time-input-container">
485
+ <input type="number" id="start-time" min="0" value="0" step="0.1">
486
+ <button class="set-time-btn" id="set-start-btn">現在の秒数に設定</button>
487
+ </div>
488
  </div>
489
  <div class="setting-item">
490
  <label for="end-time">再生終了秒数:</label>
491
+ <div class="time-input-container">
492
+ <input type="number" id="end-time" min="0" value="0" step="0.1">
493
+ <button class="set-time-btn" id="set-end-btn">現在の秒数に設定</button>
494
+ </div>
495
  </div>
496
  <div class="setting-item">
497
  <label for="loop">ループ再生:</label>
 
564
  const fullscreenBtn = document.getElementById('fullscreen-btn');
565
  const startTimeInput = document.getElementById('start-time');
566
  const endTimeInput = document.getElementById('end-time');
567
+ const setStartBtn = document.getElementById('set-start-btn');
568
+ const setEndBtn = document.getElementById('set-end-btn');
569
  const loopCheckbox = document.getElementById('loop');
570
  const globalVolumeSlider = document.getElementById('global-volume');
571
  const globalVolumeValue = document.getElementById('global-volume-value');
572
  const audioSliders = document.querySelectorAll('.audio-slider');
573
  const volumeValues = document.querySelectorAll('.volume-value');
574
+ const loadingOverlay = document.getElementById('loadingOverlay');
575
 
576
  // 音声オブジェクトを作成
577
  const audioElements = {};
578
+ const audioContexts = {};
579
+ const audioGains = {};
580
 
581
  // 音声ファイル名の配列
582
  const audioFiles = ['p', 'a', 't', 's', 'k'];
 
587
  let isVideoPlaying = false;
588
  let lastVolume = 1;
589
  let currentPlaybackRate = 1;
590
+ let allAudioLoaded = false;
591
+ let videoLoaded = false;
592
+
593
+ // ローディングアニメーションを非表示にする関数
594
+ function hideLoadingOverlay() {
595
+ loadingOverlay.style.opacity = '0';
596
+ setTimeout(function() {
597
+ loadingOverlay.style.display = 'none';
598
+ }, 1000);
599
+ }
600
+
601
+ // すべてのメディアが読み込まれたかチェック
602
+ function checkAllMediaLoaded() {
603
+ if (allAudioLoaded && videoLoaded) {
604
+ setTimeout(hideLoadingOverlay, 500);
605
+ }
606
+ }
607
 
608
  // 動画のメタデータが読み込まれたら
609
  video.addEventListener('loadedmetadata', function() {
 
612
  endTimeInput.max = videoDuration;
613
  startTimeInput.max = videoDuration - 0.1;
614
  updateTimeDisplay();
615
+ videoLoaded = true;
616
+ checkAllMediaLoaded();
617
  });
618
 
619
+ // 動画のエラー処理
620
+ video.addEventListener('error', function() {
621
+ console.error('動画の読み込み中にエラーが発生しました');
622
+ videoLoaded = true;
623
+ checkAllMediaLoaded();
624
+ });
625
+
626
+ // 再生/一時停止ボタン
627
+ playPauseBtn.addEventListener('click', function(e) {
628
+ e.stopPropagation();
629
+ togglePlayPause();
630
  });
631
 
632
+ // 時間表示を更新 (小数点以下2桁表示)
633
  function updateTimeDisplay() {
634
  const currentTime = video.currentTime;
635
  const duration = video.duration || videoDuration;
636
 
637
  const currentMinutes = Math.floor(currentTime / 60);
638
  const currentSeconds = Math.floor(currentTime % 60);
639
+ const currentMilliseconds = Math.floor((currentTime % 1) * 100);
640
  const durationMinutes = Math.floor(duration / 60);
641
  const durationSeconds = Math.floor(duration % 60);
642
+ const durationMilliseconds = Math.floor((duration % 1) * 100);
643
 
644
  timeDisplay.textContent =
645
+ `${String(currentMinutes).padStart(2, '0')}:${String(currentSeconds).padStart(2, '0')}.${String(currentMilliseconds).padStart(2, '0')} / ` +
646
+ `${String(durationMinutes).padStart(2, '0')}:${String(durationSeconds).padStart(2, '0')}.${String(durationMilliseconds).padStart(2, '0')}`;
647
 
648
  // プログレスバーを更新
649
  const progressPercent = (currentTime / duration) * 100;
650
  progressBar.style.width = `${progressPercent}%`;
 
 
 
 
 
651
 
652
+ // 現在の秒数が終了秒数を超えている場合、一時停止
653
+ const endTime = parseFloat(endTimeInput.value) || duration;
654
+ if (currentTime >= endTime) {
655
+ if (loopCheckbox.checked) {
656
  const startTime = parseFloat(startTimeInput.value) || 0;
657
  seekMedia(startTime);
658
+ if (!isPlaying) {
659
+ playMedia();
660
+ }
661
+ } else {
662
+ pauseMedia();
663
  }
664
  }
665
+ }
666
+
667
+ // 動画の時間更新イベント
668
+ video.addEventListener('timeupdate', function() {
669
+ updateTimeDisplay();
670
  });
671
 
672
  // 動画終了時の処理
 
718
 
719
  const minutes = Math.floor(hoverTime / 60);
720
  const seconds = Math.floor(hoverTime % 60);
721
+ const milliseconds = Math.floor((hoverTime % 1) * 100);
722
 
723
+ progressTime.textContent = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}.${String(milliseconds).padStart(2, '0')}`;
724
  progressTime.style.display = 'block';
725
  progressTime.style.left = `${pos * 100}%`;
726
  });
 
734
  togglePlayPause();
735
  });
736
 
 
 
 
 
 
 
737
  // 再生/一時停止をトグル
738
  function togglePlayPause() {
739
  if (isVideoPlaying) {
 
834
 
835
  // 音声ファイルをロード
836
  function loadAudioFiles() {
837
+ let loadedCount = 0;
838
+
839
  audioFiles.forEach(file => {
840
  const audio = new Audio(`${file}.mp3`);
841
  audio.preload = 'auto';
 
843
  audio.loop = false;
844
  audioElements[file] = audio;
845
 
846
+ // Web Audio API コンテキストを作成
847
+ try {
848
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
849
+ const source = audioContext.createMediaElementSource(audio);
850
+ const gainNode = audioContext.createGain();
851
+
852
+ source.connect(gainNode);
853
+ gainNode.connect(audioContext.destination);
854
+
855
+ audioContexts[file] = audioContext;
856
+ audioGains[file] = gainNode;
857
+ } catch (e) {
858
+ console.error('Web Audio API の初期化に失敗しました:', e);
859
+ }
860
+
861
  // 音声が読み込まれたら
862
  audio.addEventListener('loadedmetadata', function() {
863
  console.log(`${file}.mp3 loaded`);
864
+ loadedCount++;
865
+
866
+ if (loadedCount === audioFiles.length) {
867
+ allAudioLoaded = true;
868
+ checkAllMediaLoaded();
869
+ }
870
  });
871
 
872
  // エラー処理
873
  audio.addEventListener('error', function() {
874
  console.error(`Error loading ${file}.mp3`);
875
+ loadedCount++;
876
+
877
+ if (loadedCount === audioFiles.length) {
878
+ allAudioLoaded = true;
879
+ checkAllMediaLoaded();
880
+ }
881
  });
882
  });
883
  }
 
891
 
892
  // ボリューム設定
893
  const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
894
+ const volume = parseFloat(volumeSlider.value) * parseFloat(globalVolumeSlider.value);
895
+ if (audioGains[file]) {
896
+ audioGains[file].gain.value = volume;
897
+ } else {
898
+ audio.volume = volume;
899
+ }
900
 
901
  // 再生速度設定
902
  audio.playbackRate = currentPlaybackRate;
 
909
  audio.currentTime = playStartTime;
910
 
911
  // 再生
912
+ const playPromise = audio.play();
913
+
914
+ if (playPromise !== undefined) {
915
+ playPromise.catch(e => {
916
+ console.log("Audio play failed:", e);
917
+ // ユーザー操作がない場合、音声をミュートにして再試行
918
+ audio.muted = true;
919
+ audio.play().catch(e => console.log("Retry with mute failed:", e));
920
+ });
921
+ }
922
 
923
  // ループ設定
924
  audio.loop = loopCheckbox.checked;
 
935
 
936
  // 再生関数
937
  function playMedia() {
938
+ const currentTime = video.currentTime;
939
+ const duration = video.duration || videoDuration;
940
+ const endTime = parseFloat(endTimeInput.value) || duration;
 
 
941
 
942
  // 現在位置が終了時間を超えている場合、開始位置に戻る
943
+ if (currentTime >= endTime) {
944
+ const startTime = parseFloat(startTimeInput.value) || 0;
945
+ seekMedia(startTime);
946
  }
947
 
948
  // 動画を再生
949
+ video.play().then(() => {
950
+ isPlaying = true;
951
+ isVideoPlaying = true;
952
+ playPauseBtn.textContent = '⏸';
953
+
954
+ // 音声を再生
955
+ audioFiles.forEach(file => {
956
+ playAudio(file, video.currentTime);
957
+ });
958
+ }).catch(e => {
959
+ console.error("Video play failed:", e);
960
  });
961
  }
962
 
 
983
  volumeValues[index].textContent = value.toFixed(2);
984
 
985
  if (audioElements[this.dataset.audio]) {
986
+ const globalVolume = parseFloat(globalVolumeSlider.value);
987
+ if (audioGains[this.dataset.audio]) {
988
+ audioGains[this.dataset.audio].gain.value = value * globalVolume;
989
+ } else {
990
+ audioElements[this.dataset.audio].volume = value * globalVolume;
991
+ }
992
  }
993
  });
994
  });
 
1002
  if (audioElements[file]) {
1003
  const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
1004
  const volume = parseFloat(volumeSlider.value) * value;
1005
+ if (audioGains[file]) {
1006
+ audioGains[file].gain.value = volume;
1007
+ } else {
1008
+ audioElements[file].volume = volume;
1009
+ }
1010
  }
1011
  });
1012
  });
 
1020
  });
1021
  });
1022
 
1023
+ // 開始秒数を現在の秒数に設定
1024
+ setStartBtn.addEventListener('click', function() {
1025
+ startTimeInput.value = video.currentTime.toFixed(1);
1026
+ });
1027
+
1028
+ // 終了秒数を現在の秒数に設定
1029
+ setEndBtn.addEventListener('click', function() {
1030
+ endTimeInput.value = video.currentTime.toFixed(1);
1031
+ });
1032
+
1033
  // 初期化
1034
  loadAudioFiles();
1035
  updateVolumeIcon();
1036
  volumeSlider.value = video.volume;
1037
  video.controls = false;
1038
+
1039
+ // 現在の秒数が終了秒数より後なら、一時停止させる
1040
+ function checkCurrentTime() {
1041
+ const duration = video.duration || videoDuration;
1042
+ const endTime = parseFloat(endTimeInput.value) || duration;
1043
+
1044
+ if (video.currentTime >= endTime) {
1045
+ seekMedia(endTime);
1046
+ pauseMedia();
1047
+ }
1048
+ }
1049
+
1050
+ // 定期的にチェック
1051
+ setInterval(checkCurrentTime, 1000);
1052
  });
1053
  </script>
1054
  </body>