iOS YTPlayerView force video quality - ios

I am currently using iOS-youtube-player-helper library in our application. There is a view controller, with a YTPlayerView that has an aspect ratio of 16:9, which means it takes only a part of the screen. The video is loaded in medium and no matter how, I could not get it to play in 720P or 1080P. I am certain that these qualities are available, it's just the YTPlayerView forcing the quality based on the video player height. Because this is a library and not direct iframe embed, I cannot use "vq" parameter(specifying vq in playerVars does not seem to work), and setting the quality to be small then change it later does not work either(refer to this issue on GitHub)
Now, given the factor that I cannot make the YTPlayerView to fill up the whole screen, because of UI designing issues. So, is it possible to force the YTPlayerView to play in at least 720P? (Workarounds, changing the library code, ...)
Because this is an app that will be on App Store(and of course we don't want to have any legal disputes with google either), please don't suggest using libraries that are against the Youtube ToC such as XCDYouTubeKit
Many Thanks

I've found a workaround and this works well for me.
First of all, the problems depends by the webView size constructed inside the YTPlayerView. For example if you have a 320x200 playerView, try to forcing your video to 720hd don't work because the iFrame youtube player class re-switch to a better resolution according to your player size (in this case small quality because you have 320x200).
You can see this SO answer that explain this issue.
When you have imported the YTPlayerView class to your project you have two files: YTPlayerView.h and YTPlayerView.m
YTPlayerView.m (Update to work also on iPads)
I've change the function where the webview is initialized with a custom size (4k resolution) and to the last part I've added the possibility to scale the contents and restore the original frame, like this:
- (UIWebView *)createNewWebView {
CGRect frame = CGRectMake(0.0, 0.0, 4096.0, 2160.0); //4k resolution
UIWebView *webView = [[UIWebView alloc] initWithFrame:frame];
//UIWebView *webView = [[UIWebView alloc] initWithFrame:self.bounds];
webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
webView.scrollView.scrollEnabled = NO;
webView.scrollView.bounces = NO;
if ([self.delegate respondsToSelector:#selector(playerViewPreferredWebViewBackgroundColor:)]) {
webView.backgroundColor = [self.delegate playerViewPreferredWebViewBackgroundColor:self];
if (webView.backgroundColor == [UIColor clearColor]) {
webView.opaque = NO;
}
}
webView.scalesPageToFit = YES;
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
CGSize contentSize = webView.scrollView.contentSize;
CGSize viewSize = self.bounds.size;
float scale = viewSize.width / contentSize.width;
webView.scrollView.minimumZoomScale = scale;
webView.scrollView.maximumZoomScale = scale;
webView.scrollView.zoomScale = scale;
// center webView after scaling..
[webView setFrame:CGRectMake(0.0, self.frame.origin.y/3, 4096.0, 2160.0)];
} else {
webView.frame = self.bounds;
}
[webView reload];
return webView;
}
Hope this helps who try to use the Youtube original player in his project.
P.S.: All my tries were did with a swift project and the following vars:
var playerVars:Dictionary =
["playsinline":"1",
"autoplay":"1",
"modestbranding":"1",
"rel":"0",
"controls":"0",
"fs":"0",
"origin":"https://www.example.com",
"enablejsapi":"1",
"iv_load_policy":"3",
"showinfo":"0"]
Using the functions:
self.playerView.load(withVideoId: "Rk6_hdRtJOE", playerVars: self.playerVars)
and the follow method to force the resolution:
self.playerView.loadVideo(byId: "Rk6_hdRtJOE", startSeconds: 0.0, suggestedQuality: YTPlaybackQuality.HD720)
About iPads:
As reported by Edward in comments there was a little problem on iPads, that's because these devices seems don't apply scalesPageToFit. The goal is to check if the device is an iPad, then to scale (zooming out) the scrollView to host the little view bounds.
I've tested on my iPad air and it works. Let me know.

Related

RTCVideoTrack shows stretched WebRTC

I am using core WebRTC framework and rendering my local stream in IPhone full screen mode. Unfortunately, my video shows stretched, doesn't show like video view in camera app.
I tried to add aspect ratio in RTCMediaConstraints and also used adaptOutputFormatToWidth method to fix the output.
NSDictionary* mandatoryConstraints;
/* want to calculate aspect ratio dynamically */
NSString *aspectRatio = [NSString stringWithFormat:#"%f",(double)4/3];
if (aspectRatio) {
mandatoryConstraints = #{ kRTCMediaConstraintsMaxAspectRatio:
aspectRatio};
}
RTCMediaConstraints *cameraConstraints = [RTCMediaConstraints alloc];
cameraConstraints = [cameraConstraints initWithMandatoryConstraints:mandatoryConstraints optionalConstraints:nil];
RTCAVFoundationVideoSource *localVideoSource = [peerFactory avFoundationVideoSourceWithConstraints:mediaConstraint];
[localVideoSource adaptOutputFormatToWidth:devicewidth:devicewidth fps:30];
In below link, the difference between camera video view and my app call video view is shown
https://drive.google.com/file/d/1HN3KQcJphtC3VzJjlI4Hm-D3u2E6qmdQ/view?usp=sharing
I believe you are rendering your video in RTCEAGLVideoView, which require adjustment for size, you can use RTCMTLVideoView in place of RTCEAGLVideoView.
and if you want to use RTCEAGLVideoView, use RTCEAGLVideoViewDelegate method.
- (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size;
this method will give you correct size of the video.
(For Swift) -> Use RTCMTLVideoView and set videoContentMode
#if arch(arm64)
let renderer = RTCMTLVideoView(frame: videoView.frame)
renderer.videoContentMode = .scaleAspectFill
#else
let renderer = RTCEAGLVideoView(frame: videoView.frame)
#endif

ZXing iOS barcode scanning: ZXCapture custom camera size

I would like to use the ZXing iOS framework to bring barcode scanning to my iOS application.
After downloading the Github project (https://github.com/TheLevelUp/ZXingObjC) I played around with the iOS demo project.
In the demo project the phone camera is fullscreen - for my needs I would like to adjust the size of the camera.
ZXing is using the class 'ZXCapture' for doing live barcode scanning.
The demo app has the following viewDidLoad function:
- (void)viewDidLoad {
[super viewDidLoad];
self.capture = [[ZXCapture alloc] init];
self.capture.camera = self.capture.back;
self.capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
// here I tried to change the size of the camera
self.capture.layer.frame = CGRectMake(0, 0, 200, 200);
[self.view.layer addSublayer:self.capture.layer];
[self.view bringSubviewToFront:self.scanRectView];
[self.view bringSubviewToFront:self.decodedLabel];
}
As you can see, I added a line of code to change the size of the capture frame.
Without success... (I also tried to add the capture layer to a custom sized UIView - also without success - the camera still has a fixed size)
Has anybody ever had the same problem or use case with ZXing for iOS?
Or dose anybody has an idea to do what I want?

WKWebView shows a cropped background and blank space after rotation on iPad

I'm migrating my app from UIWebView to WKWebView for iOS8.x (maintaining support for iOS7.x) users and I'm having a trouble with the website I'm displaying, because after rotating the iPad, it displays the content but the background seems somehow cropped and therefore there is a blank space after the bg.
However as soon as I start scrolling the website, it fixes automatically by itself. This blank effect also happens when I pass from landscape to portrait orientation, which leaves the right side of the website with the blank background.
Here's how I tryed solving the issue:
(void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation duration (NSTimeInterval)duration
{
[self.view setNeedsUpdateConstraints];
[_webView setNeedsUpdateConstraints];
}
(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.view setNeedsUpdateConstraints];
[_webView setNeedsUpdateConstraints];
}
I've tried many things (reloading the background via JS, handling the willRotateToInterfaceOrientation and didRotateFromInterfaceOrientation methods as shown above) but have not been able to solve the issue, and it only happens when using WKWebView, if I switch back to UIWebView, the website renders properly.
I also tested the website on Safari for the very same device (an iPad2 with iOS 8.1.3) and it doesn't show the error, no matter how many times I rotate the iPad, so I'm sure it can be solved =). Can anybody please help me?
This is a bug in WKWebKit that's usually triggered by HTML elements with position: fixed applied. The only workaround I've found is to use window.scrollTo() to scroll the page by one pixel a few hundred miliseconds after a resize event.
This save my life:
self.wkWebView.evaluateJavaScript("window.scrollBy(1, 1);window.scrollBy(-1, -1);", completionHandler: nil)
Add this line on wkwebview did finish navigation event!!
Took me a while, but I got it working for pages without scroll:
window.addEventListener('resize', function(){
setTimeout(function () {
var vp = document.getElementsByName("viewport")[0],
vpContent = vp.content,
vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001;
vp.content = "user-scalable=no, initial-scale="+vpHack+", maximum-scale="+vpHack+", minimum-scale="+vpHack+",width=device-width";
setTimeout(function(){vp.content=vpContent;},10);
}, 500);
}, true);
That's assuming you use viewport. it changes the viewport by 0.0001 for 10 milliseconds
I implemented it like this:
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(#"###### FINISH");
[self.webView evaluateJavaScript:[NSString stringWithFormat:#"if (document.readyState==='complete'){ window.addEventListener('resize', function(){setTimeout(function () {var vp = document.getElementsByName('viewport')[0],vpContent = vp.content,vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001; vp.content = 'user-scalable=no, initial-scale='+vpHack+', maximum-scale='+vpHack+', minimum-scale='+vpHack+',width=device-width';setTimeout(function(){vp.content=vpContent;},10);}, 500);}, true); } else { window.addEventListener('load', function(){window.addEventListener('resize', function(){setTimeout(function () {var vp = document.getElementsByName('viewport')[0],vpContent = vp.content,vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001; vp.content = 'user-scalable=no, initial-scale='+vpHack+', maximum-scale='+vpHack+', minimum-scale='+vpHack+',width=device-width';setTimeout(function(){vp.content=vpContent;},10);}, 500);}, true);}, false );}"] completionHandler:nil];
}
I use document.head.appendChild(document.createElement('style')).remove();
to tickle my WKWebViews into redrawing after resize/rotate.
The following workaround worked for me, but unfortunately only on the Simulator:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// Workaround for WKWebView iOS 8 Rotation Bug
// Official Fix (iOS 9): http://trac.webkit.org/changeset/169625
if ([[[UIDevice currentDevice] systemVersion] integerValue] == 8) {
CGRect frame = self.view.frame;
frame.size.width += 1;
self.view.frame = frame;
frame.size.width -= 1;
self.view.frame = frame;
}
}
After some experimenting I got it to work on the device too using the following steps:
Keep two sets of AutoLayout constraints, the first one for the behavior you actually intend and the second with a small change (e.g. 1 point size difference)
Whenever the orientation changes, apply the second set to the view, then, after 1 second, apply the first constraints set.
While this solution is far from ideal, it is the only one I found without manipulating the Javascript on the website. I tried to lower the delay, but in my tests I had to wait for at least 0.8 seconds.

Is it possible to capture a screenshot of a whole webpage in the iOS Simulator?

Currently i am making "traditional" screenshots and combine them using a graphics editor to show the full webpage at once. Is there any more efficient way of making screenshots of a full webpage, just as by using Awesome Screenshot for Google Chrome?
(No, i do not have an iPhone ;)
You have to write it on your own.
Create a fullscreen webView inside your app.
Open page you want to open
Manipulate the property webView.scrollView to move successfully to the bottom of the page.
Capture screenshot every time
If you're on the bottom merge screenshots to one large images.
I believe this is a simplest way and run on the simulator.
See the code below.
-(NSData *)getImageFromView:(UIView *)view // Mine is UIWebView but should work for any
{
NSData *pngImg;
CGFloat max, scale = 1.0;
CGSize viewSize = [view bounds].size;
// Get the size of the the FULL Content, not just the bit that is visible
CGSize size = [view sizeThatFits:CGSizeZero];
// Scale down if on iPad to something more reasonable
max = (viewSize.width > viewSize.height) ? viewSize.width : viewSize.height;
if( max > 960 )
scale = 960/max;
UIGraphicsBeginImageContextWithOptions( size, YES, scale );
// Set the view to the FULL size of the content.
[view setFrame: CGRectMake(0, 0, size.width, size.height)];
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
pngImg = UIImagePNGRepresentation( UIGraphicsGetImageFromCurrentImageContext() );
UIGraphicsEndImageContext();
return pngImg; // Voila an image of the ENTIRE CONTENT, not just visible bit
}
I got this code from this link. Hope it will help you.

How can I embed a Youtube video in a iOS6 app?

I have problems embedding Youtube videos in a iOS6 app.
The problem is that whenever I create a html element that uses the old / or new embed code, it opens Safari and shows the video
I use the Youtube API to get videos, and use PhoneGap
Update
The solution is to set OpenAllWhitelistURLsInWebView to YES in Phonegap settings
You can use UIWebview to load videos instead of Safari.
Here is a sample code
CGRect rect = [[UIScreen mainScreen] bounds];
CGSize screenSize = rect.size;
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,screenSize.width,screenSize.height)];
webView.autoresizesSubviews = YES;
webView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
NSString *videoUrl = #"http://www.youtube.com/v/oHg5SJYRHA0";
NSString *htmlString = [NSString stringWithFormat:#"<html><head><meta name = \"viewport\" content = \"initial-scale = 1.0, user-scalable = no, width = 212\"/></head><body style=\"background:#F00;margin-top:0px;margin-left:0px\"><div><object width=\"320\" height=\"480\"><param name=\"movie\" value=\"%#\"></param><param name=\"wmode\" value=\"transparent\"></param><embed src=\"%#\" type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"320\" height=\"480\"></embed></object></div></body></html>",videoUrl,videoUrl] ;
[webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:#"http://www.youtube.com"]];
[window addSubview:webView];
[webView release];
Not shure if you are talking a real APP (dont know anything about that)
but if its a WEBAPP (a normal webpage that tries to look as a real APP),
Then the only way i found to prevent youtube-videos from opening in Safari/Qt-player
is to embed it using "Fancybox" (maybe other boxes also).
that will keep it on the page in Youtube´s own player.
You can even have a original playlistplayer.
I stopped trying to embed youtube videos on iPhone-pages (to small)
I tried to include a link to a jSfiddle-example but this forum wont accept it
it forces me to write the whole example here...which i´m not going to do
because that is to much work for me right now.
(dont know how others are allowed to link to jSfiddle)
This forum is way to dictative to my taste.
Anyway you should be able to (incase of a webapp) find info at Fancybox´s website.

Resources