马黑黑 发表于 2022-6-25 11:56

花潮LRC在线(6.25)测试版

本帖最后由 马黑黑 于 2022-6-25 12:06 编辑 <br /><br /><style>
.outer { margin: auto; width: fit-content; height: fit-content; }
.outer h2 { margin: 10px; padding: 0; font: bold 1.5em sans-serif; text-align: center; }
.outer p { margin: 10px; }
.outer input { font: normal 16px sans-serif; }
.menu { margin: 0 0 -1px 8px; width: fit-content; height: fit-content; display: flex; position: relative; }
.item { width: 60px; height: 30px; font: normal 1em / 30px sans-serif; text-align: center; background: #fff; border: 1px solid; border-bottom: none; cursor: pointer; }
.item1 { border: none; border-bottom: 1px solid; background: none; }
#slip { width: 50px; text-align: center; }
#lrcText { padding: 10px; width: 736px; height: 400px; font: normal 16px / 26px sans-serif; resize: both; border: 1px solid; outline: none; }
#mUrl {         padding: 4px; width: 440px; font-size: 14px; }
#aud { display: none; outline: none; }
#audMsg { display: inline-block; margin-left: 12px; height: 54px; font: normal 1em / 54px sans-serif; }
#up, #copy { display: none; }
#check, #invert { width: 100px; }
</style>

<div class="outer">
        <h2>花潮LRC在线</h2>
        <div class="menu">
                <div class="item">制作</div>
                <div class="item item1">转换</div>
                <div class="item item1">测试</div>
        </div>
        <textarea id="lrcText" rows ="18" cols="60" placeholder="原始歌词"></textarea>
        <p>
                <input id="begin" type="button" value=" 开始 " />
                <input id="up" type="button" value=" ↑↑ " />
                <input id="copy" type="button" value=" 复制 " />
                <input id="mUrl" type="text" placeholder="音频地址" value="" />
                <label>误差值 : </label>
                <input id="slip" type="number" placeholder="0" value="0.2" min="0" max="1" step="0.1" />
                <input id="check" type="button" value="lrc效果测试" disabled />
                <input id="invert" type="button" value="lrc转换" style="display: none" />
        </p>
        <p style="display:flex">
                <audio id="aud" controls="controls"></audio>
                <span id="audMsg"></span>
        </p>
</div>

<script>
//更新时间 2022.6.24
let begin = document.querySelector('#begin'), copy = document.querySelector('#copy'),
        up = document.querySelector('#up'), check = document.querySelector('#check'),
        invert = document.querySelector('#invert'), lrcText = document.querySelector('#lrcText'),
        slip = document.querySelector('#slip'), audMsg = document.querySelector('#audMsg'),
        mUrl = document.querySelector('#mUrl'), items = document.querySelectorAll('.item');
let lrcArr = [], slipNum = , mode = 0, yp, idx, mkidx;
//模式切换
Array.from(items).forEach((ele,key) => {
        ele.onclick = () => {
                slip.value = slipNum;
                ele.className = 'item';
                mode = key;
                if(mode == 0) { //制作模式
                        lrcText.placeholder = '原始歌词';
                        items.className = items.className = 'item item1';
                        check.disabled = true;
                        begin.disabled = false;
                        check.style.display = 'inline-block';
                        invert.style.display = 'none';
                } else if(mode == 1){ //转换模式
                        lrcText.placeholder = 'mm:(.)ss.(:)ms → ss.ms';
                        items.className = items.className = 'item item1';
                        check.disabled = true;
                        check.style.display = 'none';
                        begin.disabled = true;
                        invert.style.display = 'inline-block';
                } else { //检验模式
                        lrcText.placeholder = '花潮lrc歌词同步测试';
                        items.className = items.className = 'item item1';
                        check.disabled = false;
                        check.style.display = 'inline-block';
                        begin.disabled = true;
                        invert.style.display = 'none';
                }
        }
});
//开始制作
begin.onclick =() => {
        if(lrcText.value == '' || mUrl.value == '') return false;
        getUrl(mUrl.value);
        lrcArr.length = 0;//清空数组
        idx = mkidx = 0;
        lrcArr = (lrcText.value).trim().split('\n');
        lrcText.value = 'let lrcAr = [\n';
        mUrl.value = lrcArr;
        begin.style.display = 'none';
        up.style.display = 'inline-block';
        aud.style.display = 'inline-block';
}
//lrc上屏
up.onclick = () => {
        if(idx == lrcArr.length - 1) {//最后一句
                lrcText.value += '\t' + mUrl.value.slice(0,-1) + '\n];';
                up.style.display = 'none';
                copy.style.display = 'inline-block';
                mUrl.value = aud.src;
        } else {
                lrcText.value += '\t' + mUrl.value + '\n';
        }
        lrcText.scrollTop = lrcText.scrollHeight;
        if(idx < lrcArr.length - 1) idx ++;
        mkidx ++;
        audMsg.innerText = audMsg.innerText.replace(/\/\s\d+/,'/ ' + mkidx);
        mUrl.value = lrcArr;
}
//复制
copy.onclick = () => {
        lrcText.select();
        document.execCommand('copy');
        mUrl.value = '已复制到剪切板';
        copy.style.display = 'none';
        begin.style.display = 'inline-block';
}
//lrc效果测试
check.onclick = () => {
        if(lrcText.value == '' || mUrl.value == '') return false;
        getUrl(mUrl.value);
        lrcArr.length = 0; //清空数组
        idx = 0; //重置数组标识
        let ar = lrcText.value.split('\n');
        for(j=0; j<ar.length; j++) {
                let str = ar.replace(/\['|'],|']|\["|"],|"]|\t|\s/g,'');
                let tmpar = str.split("','");
                if(tmpar.length > 1) lrcArr.push(tmpar);
        }
        aud.style.display = 'block';
        aud.src = mUrl.value;
        aud.play();
}
//转换
invert.onclick = () => {
        if(lrcText.value == '' || mUrl.value == '') return false;
        getUrl(mUrl.value);
        let str = 'let lrcAr = [\n';
        lrcArr.length = 0; //清空数组
        lrcArr = getLrcMsg(lrcText.value);
        for(x of lrcArr) str += "\t['" + x + "','" + x + "'],\n";
        str = str.substring(0, str.lastIndexOf(','));
        lrcText.value = str + '\n];';
}
//误差值改变
slip.onchange = () => {
        slipNum = slip.value;
        if(slipNum > 1) slipNum = 1;
        if(slipNum < -1) slipNum = -1;
}
//暂停监听: 仅制作
aud.addEventListener('pause', () =>{
        if(mode == 0){
                let time = (aud.currentTime - slipNum).toFixed(2);
                mUrl.value = `['${time}','${rep(lrcArr)}'],`;
        }
});
//进度监听
aud.addEventListener('timeupdate', () =>{
        audMsg.innerText = aud.duration + ' | ' + aud.currentTime + (mode == 0 ? ' [ 完成量: ' + lrcArr.length + ' / ' + mkidx + ' ]' : '');
        if(mode == 2){ //检测模式
                let tt = aud.currentTime ;
                for(j=0; j<lrcArr.length; j++){
                        if(tt >= lrcArr - slipNum){
                                mUrl.value = lrcArr;
                                selectText(lrcArr,lrcText);
                                if(lrcText.scrollTop < lrcText.scrollHeight) lrcText.scrollTop = j * lrcText.scrollHeight / (lrcArr.length + 2);
                        }
                }
        }
});
//播放结束监听
aud.addEventListener('ended', () => mUrl.value = yp);
//处理小角引号
let rep = (str) =>str.replace(/\'/g,"\'");
//转换函数 mm:(.)ss:(.)ms → ss.ms
function getLrcMsg(text) {
        let lrcAr = []; //返回的数组
        let calcRule = ; //不同数位的分钟运算规则
        for(x of text.split('\n')) {
                let ar = [];
                let re = /\d+[\.:]\d+([\.:]\d+)?/g; //匹配 mm:(.)ss:(.)ms
                let geci = x.replace(re,''); //找词
                if(geci) { //若有词
                        geci = geci.replace(/[\[\]\'\"\t,]s?/g,''); //过滤无用字符
                        let time = x.match(re); //找时间
                        if(time != null) {
                                for(y of time) {
                                        let tmp = y.match(/\d+/g);
                                        let sec = 0;
                                        for(z in tmp) sec += tmp * calcRule;
                                        sec -= slipNum;
                                        if(sec <0) sec = 0.00;
                                        ar = ;
                                        lrcAr.push(ar);
                                }
                        }
                }
        }
        lrcAr.sort((a,b)=> a - b); //排序
        return lrcAr;
}
//选中当前句时间
let selectText = (txt,ele) =>{
        let all = ele.value,
                start = all.search(txt),
                end = start + txt.length;
        ele.setSelectionRange(start,end);
        ele.focus();
}

function getUrl(url) {
        let reg = /\.?:wav|mp3|wma|ogg|aac|ape|flac$/;
        if(reg.test(url.toLowerCase())) yp = url.trim();
        aud.src = yp;
}

</script>

马黑黑 发表于 2022-6-25 11:57

本帖最后由 马黑黑 于 2022-6-25 12:05 编辑

当前为测试之用,发布的主要目的是想通过测试收集存在问题。

主要更新:

一、改进程序一些细节逻辑性问题,比如工作模式切换后音频地址的继承或变更等等;

二、提升程序识别lrc歌词中可能存在的变种时间格式的能力;

三、制作进度的信息呈现方式得到些微改善,表现更为友好;

四、修复业已发现的个别问题。

岩新新 发表于 2022-6-25 12:00

欣赏支持!

马黑黑 发表于 2022-6-25 12:07

岩新新 发表于 2022-6-25 12:00
欣赏支持!

请{:4_190:}

加林森 发表于 2022-6-25 12:15

等会我就来试一下。

马黑黑 发表于 2022-6-25 12:16

加林森 发表于 2022-6-25 12:15
等会我就来试一下。

好的,发现问题吱一声
{:4_190:}

加林森 发表于 2022-6-25 12:17

马黑黑 发表于 2022-6-25 12:16
好的,发现问题吱一声

好的。

小辣椒 发表于 2022-6-25 12:28

马黑黑 发表于 2022-6-25 11:57
当前为测试之用,发布的主要目的是想通过测试收集存在问题。

主要更新:


黑黑我又躺床上了{:5_149:}

马黑黑 发表于 2022-6-25 13:16

小辣椒 发表于 2022-6-25 12:28
黑黑我又躺床上了

咋的啦

小辣椒 发表于 2022-6-25 13:19

马黑黑 发表于 2022-6-25 13:16
咋的啦

发烧了,空调害的

马黑黑 发表于 2022-6-25 13:21

小辣椒 发表于 2022-6-25 13:19
发烧了,空调害的

额。这没关系,很快恢复。空调还是开到合适的温度的好,比如家里可以考虑28°C,或自己穿件长袖。

加林森 发表于 2022-6-25 13:54

马黑黑 发表于 2022-6-25 12:16
好的,发现问题吱一声

已经制作出来一个了。《绿叶对根的情意》,你去看看吧。

加林森 发表于 2022-6-25 13:57

小辣椒 发表于 2022-6-25 13:19
发烧了,空调害的

又感冒了啊?多喝水排毒的。真是的,空调平均温度是根据你们那里的天气你就给着调整哦。最好26度左右就行了。

马黑黑 发表于 2022-6-25 15:30

加林森 发表于 2022-6-25 13:54
已经制作出来一个了。《绿叶对根的情意》,你去看看吧。

看到了,非常漂亮

加林森 发表于 2022-6-25 15:34

马黑黑 发表于 2022-6-25 15:30
看到了,非常漂亮

嗯嗯。这个版本应该是很成功的。

红影 发表于 2022-6-25 15:58

黑黑辛苦了,每一次的更新,知道你要花大量的功夫,太不容易了{:4_199:}

马黑黑 发表于 2022-6-25 16:00

红影 发表于 2022-6-25 15:58
黑黑辛苦了,每一次的更新,知道你要花大量的功夫,太不容易了

这次更新,写代码的时间极短的,思考的时间可能多了一些

红影 发表于 2022-6-25 16:01

美妙的花潮lrc在线,伟大的黑黑{:4_178:}

马黑黑 发表于 2022-6-25 16:02

红影 发表于 2022-6-25 16:01
美妙的花潮lrc在线,伟大的黑黑

伟大说过了{:5_117:}

马黑黑 发表于 2022-6-25 16:03

加林森 发表于 2022-6-25 15:34
嗯嗯。这个版本应该是很成功的。

做完我自己测试过两次,感觉目前的样纸还是可以接受的
页: [1] 2 3 4 5 6
查看完整版本: 花潮LRC在线(6.25)测试版