我正在开发一个java程序,可以在嵌入式播放器中播放YouTube视频。问题是,大多数音乐视频都无法播放,我遇到了以下错误:“此视频包含(媒体公司名称)的内容。某些网站限制播放。”
我尝试在Chrome加载相同的URL,结果相同。https://www.youtube.com/embed/TMZi25Pq3T8
然而,经过一些研究,我很快就修复了它,安装了一个允许我添加HTTP请求头的Chrome扩展,并添加了一个遵循此结构的Referer头。”https://www..com“并使其工作。
所以我想一定是这样。为了将请求头添加到我的JavaFX WebView/WebEngine中,我添加了以下代码:
URI uri = URI.create("https://www.youtube.com/embed/TMZi25Pq3T8");
List<String> cookies = new ArrayList<>();
cookies.add("User-Agent=BDM/v0.92");
cookies.add("Referer=https://www.youtube.com");
Map<String, List<String>> headers = new LinkedHashMap<String, List<String>>();
headers.put("Set-Cookie", cookies);
try {
CookieHandler.getDefault().put(uri, headers);
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println(webView.getEngine().getUserAgent());
webView.getEngine().load(uri.toString());
仍然没有成功,同样的错误消息。
我正在使用的网站通过他们的API Discogs提取发布数据,它也可以播放“受限”视频。我错过了什么?
后期编辑:进一步澄清:
我想为我犯的错误道歉:
这就引出了一个真正的问题:如何为JavaFX WebEngine发送HTTP请求头?唯一的选择是通过调用webView来设置用户代理。getEngine()。setUserAgent(“myUserAgent”)
我在这里找到了一个黑客,但这对我不起作用:https://twitter.com/codingfabian/status/524942996748652544
谢谢
我设法解决了这个问题,通过使用javhelp和本教程如何仪器Java代码。
正如我在问题中所说,YouTube播放器需要一个Referer标头来播放一些视频(如VEVO、Sony music Enternation等拥有的音乐视频)。
我所做的是从JavaFX的WebEngine使用的URLLoader类中截取prepareConnection方法,并将指令插入方法体的顶部:
c.setRequestProperty("Referer", "https://www.discogs.com");
(同样,请按照教程了解所有说明)
(注意:尽管上面的教程很好地解释了概念,但它并没有真正触及MANIFEST. MF文件的角色和结构,因此请查看此链接以获取有关此方面的更多信息)
这是我的两门课:
MyJavaAgent。Java语言
package com.busytrack.discographymanager.headerfixagent;
import java.lang.instrument.Instrumentation;
public class MyJavaAgent {
public static void premain(String agentArgument, Instrumentation instrumentation) {
ClassTransformer transformer = new ClassTransformer();
instrumentation.addTransformer(transformer);
}
}
ClassTransformer.java
package com.busytrack.discographymanager.headerfixagent;
import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class ClassTransformer implements ClassFileTransformer {
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
byte[] byteCode = classfileBuffer;
if (className.equals("com/sun/webkit/network/URLLoader")) {
try {
ClassPool classPool = new ClassPool(true);
CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
CtMethod method = ctClass.getDeclaredMethod("prepareConnection");
String src = "$1.setRequestProperty(\"Referer\", \"https://www.discogs.com\");"; // Confused about there being "$1" instead of "c"? Please read below
method.insertBefore(src);
byteCode = ctClass.toBytecode();
ctClass.detach();
} catch (Exception e) {
e.printStackTrace();
}
}
return byteCode;
}
}
这就是为什么我使用“$1”来访问方法参数,而不是“c”:
语句和块可以引用字段和方法。如果该方法是使用-g选项编译的,它们还可以引用它们插入的方法的参数(以在类文件中包含局部变量属性)。否则,它们必须通过下面描述的特殊变量0美元、1美元、2美元、...访问方法参数。虽然允许在块中声明新的局部变量,但不允许访问方法中声明的局部变量。
整个javassist教程都可以在这里找到。
打包两个类和清单后。MF文件放在一个单独的JAR中,将其导入IDE(我使用的是Eclipse),并添加以下VM参数:
-javaagent:./(your-jar-name).jar
在Eclipse中,可以添加如下VM参数:
right click on your project -> Run As -> Run Configurations... -> open the Arguments tab -> insert your VM argument -> Apply
我希望这对其他人有所帮助。我知道我在这个问题上花了几天时间。我不知道这是否是最好的方法,但它确实适合我。尽管如此,我还是想知道为什么没有一种简单的方法来为JavaFX的WebEngine设置请求头。。。
稍后编辑:
我发现了一种更干净、更简单的方法来动态加载Java代理,而不需要创建单独的JAR、清单文件、导入它们、在启动时传递-javaagent VM参数等等。
我使用了ea代理加载程序(JAR下载链接)。
在IDE中导入JAR,并将MyJavaAgent类(具有premain方法的类)更改为:
package com.busytrack.discographymanager.headerfixagent;
import java.lang.instrument.Instrumentation;
public class MyJavaAgent {
public static void agentmain(String agentArgument, Instrumentation instrumentation) {
ClassTransformer transformer = new ClassTransformer();
instrumentation.addTransformer(transformer);
}
}
我在MainClass中的主要方法如下所示:
public static void main(String[] args) {
AgentLoader.loadAgentClass(MyJavaAgent.class.getName(), null); // Load the MyJavaAgent class
launch(args); // Start the JavaFX application
}
我希望能够动态加载代理,因为使用静态方法需要为所有平台创建单独的启动器,并在启动时传递-javaagent参数。现在,我可以像往常一样从eclipse导出一个可运行的JAR,代理将自动加载(不需要VM参数)。感谢BioWare提供此工具!:D
所以我使用YouTube API来搜索视频。在我的搜索中,我包括以下参数:type=video,videoembeddeble=true,videoSyndicated=true。但我得到的结果仍然无法在我的网站上播放。我正在做的一个例子是 https://www.googleapis.com/youtube/v3/search?part=snippet 但是结果仍然给我一个错误,当嵌入时指出 此
问题内容: 我有一个带有angular的应用程序,我需要使用这个库http://www.jointjs.com/,所以我下载了joint.min.js和joint.min.css并将它们的路由放置在index.html中,但是我不知道要在app.js中放入什么来注入它,而我一直在从角度获取注入错误。这可能不是这样做的方法吗?我搜索了很多,但是没有找到任何方法。我将不胜感激,在此先感谢您! 问题答案
我正在尝试使用promise与我的异步函数。根据我的理解,promise应该是缓解回调地狱。然而,我的代码似乎仍然嵌套得很深。 我是否遗漏了一些关于promise的东西(是否可以重写以使其更易读/更通俗),或者promise有时就像回调一样嵌套? 在本例中,我正在构建一个函数,该函数调用API从某个社交媒体帐户检索好友列表。如果初始调用由于身份验证错误而失败,我知道我必须首先进行身份验证,然后再次
问题内容: 我知道如何在同一包中的结构中嵌入其他结构,但是如何在其他包的结构中嵌入结构? dog.go main.go 当我运行main.go时,它告诉我一个错误: 问题答案: @simon_xia是正确的,看来您 可能 对Go有点陌生。 首先,欢迎来到社区!! 现在,请扩展一下他的评论… Go并未提供成员/方法的公共/私有范围,而是具有Exporting的概念。因此,如果要允许从另一个包访问方法
问题内容: 我想启动一个将使用ajax push的应用程序,但是应该正确配置Web服务器,而且我不知道如何在服务器端组件上启动。 我想从dojo的cometd开始,然后阅读一些博客,说activeMQ较旧,并且是ajax push上的标记载体,但是还有另一个博客说,很难设置并使其工作。 现在,在开始之前我很困惑,请告诉我我的方式:)配置Ajax推送环境的最佳方法是什么? 思南 问题答案: 在斯洛文
问题内容: 我网站的合法用户有时会通过API请求对服务器进行锤击,从而导致不良结果。我想建立一个限制,即每5秒不超过一个API调用或每分钟不超过n个调用(尚未知道确切的限制)。显然,我可以将每个API调用记录在数据库中,并对每个请求进行计算,以查看它们是否超出限制,但是每个请求上的所有这些额外开销都无法达到目的。我可以使用哪些其他耗费资源较少的方法来建立限制?我正在使用PHP / Apache /