与你到永久 - 吉他的天空
本帖最后由 亚伦影音工作室 于 2025-8-15 16:38 编辑 <br /><br /><style>#bj {position: relative;
width: 1286px;
height: 720px;
margin-left: -330px;
margin-top: 10px;
overflow: hidden;z-index:12345;
background: ;
}
#vid {width: 100%; height: 100%;z-index: 1;
position:absolute;
top:0%; left:0%;
object-fit: cover; pointer-events: none;
}
.intro {margin: 0px0px;z-index:2;
width: 100%;
height:100%;
position: absolute;
background:linear-gradient(145deg, #e56420, #c22525, #3d9c31, #000078);
background-size: cover;
mix-blend-mode: hard-light;
animation: hue-rotate 3s linear infinite;
}
.stop.intro{animation-play-state: paused;}
@keyframes hue-rotate {
from {
filter: hue-rotate(0);
}
to {
filter: hue-rotate(360deg);
}
}
audio {position:absolute;top:96%;z-index:29;
width: 46%;left: 50%;
transform: translate(-50%, -50%);
height: 40px;
outline: none;
filter: invert(180);
}
audio::-webkit-media-controls-enclosure {
background:transparent ;
border-radius: 4px;
}
.media-controls-container,
.media-controls-container * {
background: rgb(129, 73, 200);
//滤镜反转为 rgba(0, 162, 255, 1);rgba(255, 93, 0, 0.8)#7eb637
border-radius: 4px;
}
audio::-webkit-media-controls-current-time-display {
order: 1; //设置弹性盒对象元素的顺序
color: #ffffff;
text-shadow: unset;
}
audio::-webkit-media-controls-time-remaining-display {
order: 2;
color: #000000;
text-shadow: unset;
}
.lyrics{margin: 0;z-index: 20;
top: 89%;
left: 50%;
transform: translate(-50%, -50%);
height: 100px; /* 调整高度,只容纳当前歌词 */
text-align: center;
position: absolute;
}
.lyric-line{
width: 100%;
position: relative;
height: 60px;
overflow: visible;
font: 300 50px '华文隶书', sans-serif;
line-height: 60px;
text-align: left;
white-space: nowrap; /* 禁止换行 */
filter: drop-shadow(#fff 1px 0 0) drop-shadow(#fff 0 1px 0) drop-shadow(#fff -1px 0 0) drop-shadow(#fff 0 -1px 0);
}
.lyric-mask {
position: absolute;
top: 0;
left: 0;
width: 0;
overflow: hidden;
color: #8B4513;
height: 100%;
white-space: nowrap;
}
.lyric-original {
color: #ag0000;
white-space: nowrap;
}
</style>
<divid="bj">
<audio id="audio" src="https://img2.oldkids.cn/upload/2025/08/13/blog_260855907_20250813175137779.mp3" autoplay loop controls></audio>
<div class='intro'></div>
<video id="vid" src="https://www.oldkids.cn/upload/2025/08/15/vedio_260855907_20250815163606792.mp4" loop muted autoplay=""></video>
<div class="lyrics" >
<div class="lyric-line">
<div class="lyric-mask"></div>
<div class="lyric-original"></div>
</div>
</div>
</div>
<script>
// 歌词解析ksc歌词或lrc歌词
const lrc = `karaoke.add('00:00.010', '00:01.529', '与你到永久 - 吉他的天空', '117,117,117,117,117,117,117,117,117,117,117,117,117');
karaoke.add('00:02.050', '00:03.788', '词:伍佰', '212,212,212,1112');
karaoke.add('00:06.490', '00:08.270', '曲:伍佰', '445,445,445,445');
karaoke.add('00:16.770', '00:18.408', '风儿轻轻的吹', '373,173,173,173,173,573');
karaoke.add('00:20.110', '00:22.614', '雨也绵绵下个不停', '438,338,138,138,338,138,438,538');
karaoke.add('00:24.120', '00:25.800', '望着走过的脚印', '340,240,140,140,140,340,340');
karaoke.add('00:27.000', '00:29.316', '有崎岖有平静', '536,236,336,336,236,636');
karaoke.add('00:31.320', '00:33.168', '看着你的眼睛', '408,208,308,308,208,408');
karaoke.add('00:34.270', '00:36.720', '我最熟悉的表情', '450,250,250,250,450,350,450');
karaoke.add('00:37.920', '00:39.230', '一路上有你', '262,262,262,262,262');
karaoke.add('00:39.730', '00:41.040', '因为有了你', '262,262,262,262,262');
karaoke.add('00:41.540', '00:45.446', '人生旅程不再冷清', '349,178,226,432,284,31,435,1971');
karaoke.add('00:47.460', '00:50.218', '迎着风', '886,586,1286');
karaoke.add('00:50.620', '00:53.117', '迎向远方的天空', '401,101,301,351,451,411,481');
karaoke.add('00:54.280', '00:55.498', '路上也有艰难', '203,203,203,203,203,203');
karaoke.add('00:56.400', '00:57.910', '也有那解脱', '233,100,705,70,402');
karaoke.add('00:58.310', '01:00.663', '都走得从容', '732,32,48,758,783');
karaoke.add('01:02.470', '01:03.801', '因为你是我', '263,218,418,153,105');
karaoke.add('01:05.200', '01:09.704', '生命中的所有', '574,315,218,218,261,2918');
karaoke.add('01:11.010', '01:13.772', '将我的心放在你手中', '342,342,436,523,159,49,207,83,623');
karaoke.add('01:14.590', '01:17.635', '陪你到永久', '396,182,122,423,1922');
karaoke.add('01:35.030', '01:36.920', '风儿轻轻的吹', '176,146,136,146,446,846');
karaoke.add('01:38.380', '01:41.088', '雨也绵绵下个不停', '126,26,426,226,326,126,426,1026');
karaoke.add('01:42.290', '01:44.070', '望着走过的脚印', '340,140,340,140,140,340,340');
karaoke.add('01:45.130', '01:48.346', '有崎岖有平静', '636,336,336,636,636,636');
karaoke.add('01:49.590', '01:51.560', '看着你的眼睛', '395,195,195,395,395,395');
karaoke.add('01:52.460', '01:54.947', '我最熟悉的表情', '441,441,141,141,441,441,441');
karaoke.add('01:56.060', '01:57.328', '一路上有你', '256,256,256,256,256');
karaoke.add('01:57.830', '01:59.180', '因为有了你', '270,270,270,270,270');
karaoke.add('01:59.680', '02:03.120', '人生旅程不再冷清', '280,280,180,480,480,180,380,1180');
karaoke.add('02:05.620', '02:08.320', '迎着风', '900,900,900');
karaoke.add('02:08.820', '02:11.886', '迎向远方的天空', '438,438,438,438,438,438,438');
karaoke.add('02:12.390', '02:13.986', '路上也有艰难', '266,266,266,266,266,266');
karaoke.add('02:14.490', '02:15.970', '也有那解脱', '296,296,296,296,296');
karaoke.add('02:16.470', '02:18.810', '都走得从容', '328,528,428,328,728');
karaoke.add('02:20.610', '02:22.820', '因为你是我', '442,442,442,442,442');
karaoke.add('02:23.320', '02:28.278', '生命中的所有', '393,193,493,493,193,3193');
karaoke.add('02:29.180', '02:31.758', '将我的心放在你手中', '342,342,342,342,342,342,142,342,42');
karaoke.add('02:32.760', '02:37.720', '陪你到永久', '552,552,552,52,3252');
`;
const audio = document.getElementById('audio');
const lyrics = parseLyrics(lrc);
const lyricMask = document.querySelector('.lyric-mask');
const lyricOriginal = document.querySelector('.lyric-original');
let currentIndex = -1;
let currentLyric = null;
// 解析歌词(支持两种格式)
function parseLyrics(lrcText) {
const lyrics = [];
if (lrcText.includes('karaoke.add')) {
const lineRegex = /karaoke\.add\('([^']+)', '([^']+)', '([^']+)', '([^']+)'\);/g;
let match;
while ((match = lineRegex.exec(lrcText)) !== null) {
const startTime = timeToMs(match);
const endTime = timeToMs(match);
const text = match.replace(/\[|\]/g, '').trim();
const durations = match.split(',').map(Number);
if (text) {
lyrics.push({startTime, endTime, text, durations});
}
}
}
else if (lrcText.includes('[')) {
const lines = lrcText.split('\n').filter(line => line.trim());
lines.forEach((line, index) => {
const timeMatch = line.match(/\[(\d+:\d+\.\d+)\]/);
if (timeMatch) {
const timeStr = timeMatch;
const text = line.replace(/\[.*?\]/, '').trim();
if (text) {
const startTime = timeToMs(timeStr);
const nextLine = lines;
const nextTimeMatch = nextLine ? nextLine.match(/\[(\d+:\d+\.\d+)\]/) : null;
const endTime = nextTimeMatch ? timeToMs(nextTimeMatch) : startTime + 5000;
lyrics.push({
startTime,
endTime,
text,
durations: calculateCharDurations(text, startTime, endTime)
});
}
}
});
}
return lyrics;
}
function calculateCharDurations(text, startTime, endTime) {
const totalDuration = endTime - startTime;
const charCount = text.length;
const baseDur = Math.floor(totalDuration / charCount);
const durations = new Array(charCount).fill(baseDur);
const remainder = totalDuration % charCount;
for (let i = 0; i < remainder; i++) {
durations++;
}
return durations;
}
function timeToMs(timeStr) {
const parts = timeStr.split(':');
const minutes = parseInt(parts, 10);
const secondsAndMs = parts.split('.');
const seconds = parseInt(secondsAndMs, 10);
const ms = parseInt(secondsAndMs || 0, 10);
return minutes * 60 * 1000 + seconds * 1000 + ms;
}
function getCurrentLyricIndex(lyrics, currentTimeMs) {
for (let i = 0; i < lyrics.length; i++) {
if (currentTimeMs >= lyrics.startTime && currentTimeMs <= lyrics.endTime) {
return i;
}
}
return -1;
}
function updateLyricDisplay(index) {
if (index < 0 || index >= lyrics.length) return;
currentIndex = index;
currentLyric = lyrics;
lyricOriginal.textContent = currentLyric.text;
lyricMask.textContent = currentLyric.text;
lyricMask.style.width = '0%';
}
function updateLyricMask(currentTimeMs) {
if (!currentLyric) return;
const lyricStartTime = currentLyric.startTime;
const elapsed = currentTimeMs - lyricStartTime;
const totalDuration = currentLyric.durations.reduce((sum, d) => sum + d, 0);
let charIndex = 0;
let accumulatedTime = 0;
for (let i = 0; i < currentLyric.durations.length; i++) {
accumulatedTime += currentLyric.durations;
if (elapsed <= accumulatedTime) {
charIndex = i + 1;
break;
}
}
if (elapsed >= totalDuration) {
charIndex = currentLyric.text.length;
}
charIndex = Math.min(charIndex, currentLyric.text.length);
const tempSpan = document.createElement('span');
tempSpan.style.visibility = 'hidden';
tempSpan.style.position = 'absolute';
tempSpan.style.fontSize = '50px';
tempSpan.style.fontWeight = '800';
document.body.appendChild(tempSpan);
const visibleText = currentLyric.text.substring(0, charIndex);
tempSpan.textContent = visibleText;
const width = tempSpan.offsetWidth;
document.body.removeChild(tempSpan);
lyricMask.style.width = `${width}px`;
}
// 监听更新歌词
audio.addEventListener('timeupdate', () => {
const currentTimeMs = audio.currentTime * 1000;
const index = getCurrentLyricIndex(lyrics, currentTimeMs);
if (index !== currentIndex) {
updateLyricDisplay(index);
}
updateLyricMask(currentTimeMs);
});
updateLyricDisplay(0);
</script>
<script>
const intro= document.querySelector('.intro');
let mState = () => audio.paused ? (intro.classList.add('stop'),vid.pause() ):(intro.classList.remove('stop'),vid.play());
audio.addEventListener('play', () => mState());
audio.addEventListener('pause', () => mState());
</script> 欣赏老师新作,学习了!
漂亮!谢谢亚伦老师精彩分享{:4_190:} 视频中的人物是AI制作的么,真漂亮啊。
欣赏亚伦老师好帖{:4_199:} 唯美的视频与清脆的乐声令人心身舒畅。 本帖最后由 偶然~ 于 2025-8-17 15:37 编辑
这样的视频播放器真的是独一无二的,亚伦影音工作室视频播放器特别有创意,尤其是片中声音与画面的结合达到了音画合一,让我感觉要偷去制作一首我的原创歌曲的冲动,感谢亚伦影音工作室带来的精彩~!
页:
[1]