how to play audio from parse.com in swift 2 - swift2

i am trying to play audio from parse.com. I am getting the pffile but unable to play audio.
func testing() {
let query = PFQuery(className: "Attractions")
query.whereKey("objectId", equalTo: "hDyP0SwbAQ")
query.findObjectsInBackgroundWithBlock { (result, error) -> Void in
for obj in result! {
let path = obj.objectForKey("attraction_file") as! PFFile
self.playWithURL(path)
}
}
}
func playWithURL(url:PFFile) {
do {
let audioPlayer = try! AVAudioPlayer(contentsOfURL: url)
audioPlayer.prepareToPlay()
audioPlayer.play()
}
}
Thanks In Advance

I Found Answer.
earlier i was using AVAudioPlayer thats why i was getting the error.
now i am using AVPlayer and my code is working perfect.
var avAudioPlayer: AVPlayer? // declared in class
func testing() {
let query = PFQuery(className: "Attractions")
query.whereKey("objectId", equalTo: "hDyP0SwbAQ")
query.findObjectsInBackgroundWithBlock { (result, error) -> Void in
for obj in result! {
let path = obj.objectForKey("SongFile") as! PFFile
self.playWithURL(path)
}
}
}
fun playWithUrl(url : String) {
self.avAudioPlayer = AVPlayer(URL: NSURL(string: url!)!)
avAudioPlayer?.play()
}

Related

Can't play video from AVCaptureFileOutput

I can't play the video the comes from the AVCaptureFileOutputDelegate. I think I'm missing something here's my code.
func recordVideo() {
let recordingDelegate: AVCaptureFileOutputRecordingDelegate? = self
self.session!.addOutput(videoFileOutput)
self.session!.sessionPreset = AVCaptureSessionPresetHigh
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let filePath = documentsURL.appendingPathComponent("temp")
videoFileOutput.startRecording(toOutputFileURL: filePath, recordingDelegate: recordingDelegate)
}
and on the delegate.
func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
if error == nil {
print("Play: \(outputFileURL!)")
self.playVideo(path: outputFileURL!)
} else {
print(error)
}
return
}
But the video is not playing. I think I'm missing the file name or something. Pls help. Thanks!

Swift 3: UICollectionView download video snapshot. UI is freezed while trying to download snapshot

I'm trying to download video preview base on remote video URL. In my project, the server cannot return snapshot image of the videos, that's why I have to do it manually.
In table view, I have code like this in cellForItemAt to get video preview
DataManager.sharedInstance.getCachedImage(url: movie.url!, handler: { (image) in
cell.ivCover.image = image
})
and my getCachedImage function in DataManager:
func getCachedImage(url: String, handler: #escaping(_ result:UIImage) -> Void){
DispatchQueue.global().async {
let userDefaults = UserDefaults.standard
if let imageData = userDefaults.object(forKey: url){
if let finalImg = UIImage(data: imageData as! Data){
DispatchQueue.main.async {
handler(finalImg)
}
print("USING CACHED IMG")
}else{
DispatchQueue.main.async {
handler(#imageLiteral(resourceName: "cover"))
}
print("Cannot parse cached data to image. Use default")
}
}else{
let asset = AVURLAsset(url: URL(string: url)!)
let generate = AVAssetImageGenerator(asset: asset)
generate.appliesPreferredTrackTransform = true
var thumbTime = asset.duration
thumbTime.value = 1
var imgRef:CGImage?
do{
print("Downloading thum from url: \(url)")
imgRef = try generate.copyCGImage(at: thumbTime, actualTime: nil)
}catch let error{
print("Error download thum: \(error.localizedDescription)")
}
var finalImg:UIImage
if let _ = imgRef{
finalImg = UIImage(cgImage: imgRef!)
userDefaults.set(UIImagePNGRepresentation(finalImg), forKey: url)
}else{
finalImg = #imageLiteral(resourceName: "cover")
print("Download thumnail failed. Use default")
}
DispatchQueue.main.async {
handler(finalImg)
}
}
}
}
The problem is that, sometimes I scroll the Collection view, UI is freezed, sometimes it's not. Please note that this video is on REMOTE SERVER, NOT local video.
I've spent days to figure out the issue but still not able to find out what went wrong. Please help!
Or is there any existing library I can use?
import UIKit
import Photos
class ImportViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func myButton(_ sender: Any) {
let videoURL = "https://youerdomin.com/file.mp4"
print("1")
DispatchQueue.global(qos: .background).async {
print("2")
if let url = URL(string: videoURL), let urlData = NSData(contentsOf: url) {
print("3")
let documentsPath =
NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath="\(documentsPath)/tempFile.mp4"
DispatchQueue.main.async {
print("4")
urlData.write(toFile: filePath, atomically: true)
PHPhotoLibrary.shared().performChanges({
print("5")
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
}) { completed, error in
print("6")
if completed {
print("Video is saved!")
}else{
print("7: ",filePath)
}
}
}
}else{
print("8")
}
}
}
}

AV Foundation Transition Music Stopping

I am using the following code to play music. It plays well :)
var backgroundMusicPlayer = AVAudioPlayer()
func playBackgroundMusic(filename: String) {
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
guard let newURL = url else {
print("Could not find file: \(filename)")
return
}
do {
backgroundMusicPlayer = try AVAudioPlayer(contentsOfURL: newURL)
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play()
} catch let error as NSError {
print(error.description)
}
}
playBackgroundMusic("music.wav")
However, I'd like to be able to keep the music playing only through certain transitions. Is this possible?
Cheers :)

iOS 9(Swift 2.0): cannot invoke 'dataTaskwithURL' with an argument list of type '(NSURL, (_, _,_)throws -> Void)'

My app works perfectly fine with iOS 8 but yesterday I upgraded to iOS 9 and Xcode 7 then my app crashes. The error message is cannot invoke 'dataTaskwithURL' with an argument list of type '(NSURL, (_, ,)throws -> Void)'. I googled it and found a similar question here but the solution didn't really work (the solution was to add the do/catch blocks around the code). Can anyone help me with mine problem? Thank you!!!
Here's my code
import UIKit
import Foundation
import CoreLocation
class GoogleDataProvider {
let apiKey = "AIzaSyCQo-clIkek87N99RVh2lmFX9Mu9QPhAtA"
let serverKey = "AIzaSyBzmv7wPFcPAe1ucy5o6dqaXnda9i9MqjE"
var photoCache = [String:UIImage]()
var placesTask = NSURLSessionDataTask()
var session: NSURLSession {
return NSURLSession.sharedSession()
}
func fetchPlacesNearCoordinate(coordinate: CLLocationCoordinate2D, radius:Double, types:[String],keyword:String, completion: (([GooglePlace]) -> Void)) -> ()
{
var urlString = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=\(serverKey)&location=\(coordinate.latitude),\(coordinate.longitude)&radius=\(radius)&keyword=\(keyword)&rankby=prominence&sensor=true"
let typesString = types.count > 0 ? types.joinWithSeparator("|") : "food"
urlString += "&types=\(typesString)"
urlString = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
if placesTask.taskIdentifier > 0 && placesTask.state == .Running {
placesTask.cancel()
}
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
do{
//******************Here's the line that displays error
placesTask = session.dataTaskWithURL(NSURL(string: urlString)!) {
(data, response, error) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
var placesArray = [GooglePlace]()
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? NSDictionary {
if let results = json["results"] as? NSArray {
for rawPlace:AnyObject in results {
let place = GooglePlace(dictionary: rawPlace as! NSDictionary, acceptedTypes: types)
placesArray.append(place)
if let reference = place.photoReference {
self.fetchPhotoFromReference(reference) { image in
place.photo = image
}
}
}
}
}
dispatch_async(dispatch_get_main_queue()) {
completion(placesArray)
}
}
}catch{
}
placesTask.resume()
}
func fetchDirectionsFrom(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D, completion: ((String?) -> Void)) -> ()
{
let urlString = "https://maps.googleapis.com/maps/api/directions/json?key=\(serverKey)&origin=\(from.latitude),\(from.longitude)&destination=\(to.latitude),\(to.longitude)&mode=walking"
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
do{
//******************************Here too ****************************
session.dataTaskWithURL(NSURL(string: urlString)!) {
(data, response, error) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
var encodedRoute: String?
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? [String:AnyObject] {
if let routes = json["routes"] as AnyObject? as? [AnyObject] {
if let route = routes.first as? [String : AnyObject] {
if let polyline = route["overview_polyline"] as AnyObject? as? [String : String] {
if let points = polyline["points"] as AnyObject? as? String {
encodedRoute = points
}
}
}
}
}
dispatch_async(dispatch_get_main_queue()) {
completion(encodedRoute)
}
}.resume()
}catch{
}
}
}
Sorry this is my first time posting the code style is a little bit confusing sorry about the indentation mess :)
Thanks again!!!
dataTaskWithURL:completionHandler: does not throw error.
Put do and catch inside dataTaskWithURL method.
for example:
session.dataTaskWithURL(NSURL(string: urlString)!) {
(data, response, error) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
var encodedRoute: String?
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? [String:AnyObject] {
if let routes = json["routes"] as AnyObject? as? [AnyObject] {
if let route = routes.first as? [String : AnyObject] {
if let polyline = route["overview_polyline"] as AnyObject? as? [String : String] {
if let points = polyline["points"] as AnyObject? as? String {
encodedRoute = points
}
}
}
}
}
} catch {
}
dispatch_async(dispatch_get_main_queue()) {
completion(encodedRoute)
}
}.resume()

Force audio file playback through iPhone loud speaker using Swift

I have an App that records and then plays back an audio file. Currently the audio playback is playing through the earpiece speaker. Could someone tell me how Swift would handle coding this to force the audio out the loud speaker instead?
Below is a one of the instances I'm using to play the audio file:
#IBAction func playAudioVader(sender: UIButton) {
playAudioWithVariablePitch(-1000)
}
func playAudioWithVariablePitch(pitch: Float){
audioPlayer.stop()
audioEngine.stop()
audioEngine.reset()
var audioPlayerNode = AVAudioPlayerNode()
audioEngine.attachNode(audioPlayerNode)
var changePitchEffect = AVAudioUnitTimePitch()
changePitchEffect.pitch = pitch
audioEngine.attachNode(changePitchEffect)
audioEngine.connect(audioPlayerNode, to: changePitchEffect, format: nil)
audioEngine.connect(changePitchEffect, to: audioEngine.outputNode, format: nil)
audioPlayerNode.scheduleFile(audioFile, atTime: nil, completionHandler: nil)
audioEngine.startAndReturnError(nil)
audioPlayerNode.play()
}
override func viewDidLoad() {
super.viewDidLoad()
audioPlayer = AVAudioPlayer(contentsOfURL:receivedAudio.filePathURL, error: nil)
audioPlayer.enableRate = true
audioEngine = AVAudioEngine()
audioFile = AVAudioFile(forReading:receivedAudio.filePathURL, error: nil)
}
EDIT July 2017: Refer to Husam's answer for the Swift 2.0 solution.
As of Swift 1.2, you use overrideOutputAudioPort and AVAudioSessionPortOverride. It can be implemented by doing something like this:
if !session.overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, error:&error) {
println("could not set output to speaker")
if let e = error {
println(e.localizedDescription)
}
}
I'm working on an app that uses this now, and I have a function called setSessionPlayandRecord, which looks like:
func setSessionPlayAndRecord() {
let session:AVAudioSession = AVAudioSession.sharedInstance()
var error: NSError?
if !session.setCategory(AVAudioSessionCategoryPlayAndRecord, error:&error) {
println("could not set session category")
if let e = error {
println(e.localizedDescription)
}
}
if !session.overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, error:&error) {
println("could not set output to speaker")
if let e = error {
println(e.localizedDescription)
}
}
if !session.setActive(true, error: &error) {
println("could not make session active")
if let e = error {
println(e.localizedDescription)
}
}
}
Swift 2.0 Code
func setSessionPlayerOn()
{
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker)
} catch _ {
}
}
func setSessionPlayerOff()
{
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch _ {
}
}

Resources