Board logo

标题: [文本处理] [已解决]求解自定义协议(URL Protocol)传参被URI编码后的URI解码问题 [打印本页]

作者: 极品小猫    时间: 2018-12-4 09:52     标题: [已解决]求解自定义协议(URL Protocol)传参被URI编码后的URI解码问题

楼主是个爱偷懒的奇葩,希望在不依赖于 Chrome 插件的情况下,楼主企图利用自定义协议去启动本地的 FFMPEG 来保存 M3U8 的视频。

FFmpeg自定义协议注册表
  1. Windows Registry Editor Version 5.00
  2. [HKEY_CLASSES_ROOT\ffmpeg]
  3. @="URL:ffmpeg Protocol"
  4. "URL Protocol"=""
  5. [HKEY_CLASSES_ROOT\ffmpeg\shell]
  6. [HKEY_CLASSES_ROOT\ffmpeg\shell\open]
  7. [HKEY_CLASSES_ROOT\ffmpeg\shell\open\command]
  8. @="\"D:\\Software_Temp\\M3U8 Downloader 0.1.1\\Tools\\ffmpeg.bat\" \"%1\""
复制代码
Bat 内容
  1. @echo off
  2. cd /d %~p0
  3. for /f "tokens=1,2 delims=," %%i in (%1) do (
  4. set url=%%i
  5. set filename=%%j
  6. )
  7. ffmpeg.exe -i "%url:~9%" -c copy -y -bsf:a aac_adtstoasc "F:\Download_M3U8\%filename%.mp4"
  8. rem ffmpeg.exe" -i "%%i" -c copy -y -bsf:a aac_adtstoasc "%%j.mp4"
  9. echo.
  10. echo 视频下载完成
  11. pause
复制代码
但 URL Protocol 传送的参数会进行URI编码,导致无法使用传送的中文内容来保存

如:
  1. ffmpeg://www.baidu.com,百度
复制代码
得到的是
  1. ffmpeg://www.baidu.com,%E7%99%BE%E5%BA%A6
复制代码
我想尝试改为使用 JS 来运行ffmpeg,但是 JS 似乎无法得到传参的内容,VBS 没有URI的解码函数。

求大神支招,该如何对这个 URI 进行解码,并作为文件名输出。

JS、VBS、Bat 三种方案都可以,混编也行。

纯 JS 解决方案
注册表
  1. [HKEY_CLASSES_ROOT\ffmpeg]
  2. @="URL:ffmpeg Protocol"
  3. "URL Protocol"=""
  4. [HKEY_CLASSES_ROOT\ffmpeg\shell\open\command]
  5. @="wscript -nologo -e:jscript \"D:\\Software_Temp\\M3U8 Downloader 0.1.1\\Tools\\ffmpeg.js\" \"%1\""
复制代码
最后解决方案使用纯 JS 来进行
原来之前以为 Arguments 是 WSH 的属性,所以一直没有得到参数。
  1. var wsh=new ActiveXObject("WScript.Shell");
  2. //获得 URL Protocol 参数,并进行数组分割,WScript.Arguments的下标使用圆括号,数组为方括号
  3. var Args=WScript.Arguments(0).split(",");
  4. var ProgramFloder=WScript.ScriptFullName.replace(/[^\\]+$/,''),
  5. Program=ProgramFloder+"ffmpeg.exe",
  6. M3U8Url=Args[0].replace(/^ffmpeg:\/\//i,''),
  7. webTitle=decodeURIComponent(Args[1]).replace(/[\/|*?"<>:]/gm,'_');
  8. wsh.Run("\""+Program+"\""+" -i "+M3U8Url+" -c copy -y -bsf:a aac_adtstoasc F:\\Download_M3U8\\"+webTitle+".mp4");
复制代码

作者: 523066680    时间: 2018-12-4 10:47

本帖最后由 523066680 于 2018-12-4 10:59 编辑

很久没用过VBS了,方案应该有,只是我不知道。
python 做这个事情很简单。Perl里面有个 URI::Escape 处理这个,也可以不用URI::Escape,自己转。

举个栗子,两种方式
  1. use Encode;
  2. use URI::Escape;
  3. my $s1 = 'ffmpeg://www.baidu.com,%E7%99%BE%E5%BA%A6';
  4. $s1 =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
  5. printf "%s\n", encode('gbk', decode('utf8', $s1));
  6. my $s2 = 'ffmpeg://www.baidu.com,%E7%99%BE%E5%BA%A6';
  7. printf "%s\n", encode('gbk', decode('utf8', uri_unescape($s1)));
复制代码

作者: Batcher    时间: 2018-12-4 11:06

http://bbs.bathome.net/thread-6084-1-1.html
http://bbs.bathome.net/thread-32032-1-1.html
作者: 极品小猫    时间: 2018-12-4 11:32

纯 JS 解决方案
注册表
  1. [code][HKEY_CLASSES_ROOT\ffmpeg]
  2. @="URL:ffmpeg Protocol"
  3. "URL Protocol"=""
  4. [HKEY_CLASSES_ROOT\ffmpeg\shell\open\command]
  5. @="wscript -nologo -e:jscript \"D:\\Software_Temp\\M3U8 Downloader 0.1.1\\Tools\\ffmpeg.js\" \"%1\""
复制代码
[/code]

最后解决方案使用纯 JS 来进行
原来之前以为 Arguments 是 WSH 的属性,所以一直没有得到参数。
  1. var wsh=new ActiveXObject("WScript.Shell");
  2. //获得 URL Protocol 参数,并进行数组分割,WScript.Arguments的下标使用圆括号,数组为方括号
  3. var Args=WScript.Arguments(0).split(",");
  4. var ProgramFloder=WScript.ScriptFullName.replace(/[^\\]+$/,''),
  5. Program=ProgramFloder+"ffmpeg.exe",
  6. M3U8Url=Args[0].replace(/^ffmpeg:\/\//i,''),
  7. webTitle=decodeURIComponent(Args[1]).replace(/[\/|*?"<>:]/gm,'_');
  8. wsh.Run("\""+Program+"\""+" -i "+M3U8Url+" -c copy -y -bsf:a aac_adtstoasc F:\\Download_M3U8\\"+webTitle+".mp4");
复制代码

作者: 极品小猫    时间: 2018-12-4 11:33

回复 2# 523066680


    已使用纯 JS 解决问题,这个问题如果使用第三方的方式确实很好搞
作者: flashercs    时间: 2018-12-4 11:33

ffmpeg.js
  1. if (WScript.Arguments.length === 0) WScript.Quit(1);
  2. var a = WScript.Arguments(0).split(',');
  3. var url = a[0];
  4. var filename = a[1] + '.mp4';
  5. var fileDir = 'F:\\Download_M3U8';
  6. var cmd = 'ffmpeg.exe -i "' + url.slice(9) + '" -c copy -y -bsf:a aac_adtstoasc "' + fileDir + '\\' + filename + '"';
  7. WScript.CreateObject('WScript.Shell').Run(cmd, 1, true);
  8. WScript.CreateObject('Scripting.FileSystemObject').GetFile(fileDir + '\\' + encodeURI(filename)).Name = filename;
  9. WScript.Echo('视频下载完成');
复制代码

作者: 极品小猫    时间: 2018-12-4 11:34

回复 3# Batcher


    感谢帮助,不过希望尽量不使用第三方命令来完成。现在使用纯 JS 来解决问题了
作者: Batcher    时间: 2018-12-4 13:02

回复 7# 极品小猫


    嗯,哪两个帖子里面也是用的 encodeURIComponent decodeURIComponent




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2